Проверка бина JSR-303 - избегайте обхода поля - PullRequest
0 голосов
/ 15 февраля 2019

Предположим, у нас есть этот компонент

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

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

   //getters and setters
}

Теперь в пользовательском интерфейсе сотрудника есть что-то вроде этого:

<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 отключен, и мы все еще хотим использовать пружинное связывание

1 Ответ

0 голосов
/ 15 февраля 2019
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 Доступ запрещен!

...