【问题标题】:JSR-303 bean validation - avoid bypassing a fieldJSR-303 bean 验证 - 避免绕过字段
【发布时间】:2019-02-15 02:21:13
【问题描述】:

假设我们有这个 bean

public class Bean {
   @NotBlank(groups = {CheckForEmployee.class, CheckForAdmins.class})
   private String sth1;

   @NotBlank(groups = {CheckForAdmins.class})
   private String sth2;

   //getters and setters
}

现在在 Employee UI 中我们有这样的东西:

<input name="sth1" type="text" />

这是给管理员的:

<input name="sth1" type="text" />
<input name="sth2" type="text" />

我们都知道像 Spring 这样的框架可以将这些值绑定到 Bean 对象,例如在 Spring 中我们有这样的东西:

public ModelAndView method1 (@Validated({CheckForEmployee.class})@ModelAttribute Bean bean){...} 
//For Employee
AND
public ModelAndView method2 (@Validated({CheckForAdmin.class})@ModelAttribute Bean bean){...} 
//For Admin

现在问题来了: 如果恶意员工知道有一个名为 "sth2" 的字段供管理员使用,他可以手动生成发布请求并设置值sth2 并将其发送到服务器。

Spring 会绑定这个值,因为:

  1. 该字段在 Bean 类中
  2. 没有针对员工的 sth2 验证

您对此有什么解决方案?

假设 CSRF 被禁用,我们仍然想使用 spring 绑定

【问题讨论】:

    标签: java spring spring-security bean-validation


    【解决方案1】:
    public class Bean {
    
        @NotBlank(groups = Validator.CheckForEmployee.class)
        private String sth1;
    
    
        @BlockAccess(groups = Validator.CheckForEmployee.class)
        @NotBlank(groups = Validator.CheckForAdmin.class)
        private String sth2;
    
        //getters and setters
    }
    
    public class Validator {
        public interface CheckForEmployee{}
        public interface CheckForAdmin{}
    }
    
    
    @Target({ElementType.FIELD, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = BlockAccessImpl.class)
    @Documented
    public @interface BlockAccess {
        String message() default "Access is denied!";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    
    }
    
    public class BlockAccessImpl implements ConstraintValidator<BlockAccess, Object> {
    
        @Override
        public void initialize(BlockAccess constraintAnnotation) {
    
        }
    
        @Override
        public boolean isValid(Object value, ConstraintValidatorContext context) {
            return false;
        }
    }
    
    public class Test {
    
        public static void main(String[] args) {
            ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
            Validator validator = factory.getValidator();
            Bean b = new Bean();
            b.setSth1("Hi");
            b.setSth2("Bye");
    
            Set<ConstraintViolation<Bean>> s = validator.validate(b, Validator.CheckForEmployee.class);
    
            for (ConstraintViolation<Bean> f : s) {
                System.out.println(f.getPropertyPath() + " " + f.getMessage());
            }
        }
    }
    

    sth2 访问被拒绝!

    【讨论】:

      猜你喜欢
      • 2015-01-10
      • 1970-01-01
      • 2013-11-23
      • 1970-01-01
      • 2011-07-24
      • 2011-06-18
      • 2011-01-31
      • 2011-10-23
      • 2016-06-21
      相关资源
      最近更新 更多