java - JSR-303 bean 验证 - 避免绕过字段
问题描述
假设我们有这个 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 将绑定这个值,因为:
- 该字段在 Bean 类中
- 没有对员工的 sth2 进行验证
您对此有何解决方案?
假设 CSRF 被禁用,我们仍然想使用 spring 绑定
解决方案
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 访问被拒绝!
推荐阅读
- jenkins - 当特定的 Github 文件更改时,是否有一个插件可以触发 Jenkins 构建?
- python - Python:对象未添加到自身
- asp.net - asp.net C# GridView 运行两次。重复结果
- reactjs - 如何摆脱网站对于 api 来说是不安全的
- javascript - 使用 d3 单击时将线从一个 svg 形状连接到其他 svg 形状
- python - 是否可以在任何 Python 求解器中运行 for 循环?
- f# - 是否可以强制在另一种类型中使用可区分联合中的类型?
- typescript - 在 Typescript 中连接随机数
- c++ - int* ptr 的区别;和 int *ptr; C++ 指针
- python - 如何使用装饰器将函数的结果包装在多个外部库函数中