简体   繁体   中英

How to use session attribute (captcha code) in custom JSR-303 Bean Validation constraint?

I want to move my captcha-code validation from Spring MVC controller to class representing posted from, because it is the last element that is not checked using JSR-303 API.

Basically, how to inject HttpSession or HttpServletRequest into JSR-303 contraint or Spring @ModelAttribute representing posted form data to validate captcha input?

Suppose we have a captcha code in "captcha_code" session attribute, how to write JSR-303 custom constraint that will compare input to that session attribute? Like:

class RegisterForm {

 ... email, password etc. ...

 @NotNull
 @Length( min = 6 , max = 6 )
 @EqualsToSessionAttribute("captcha_code") // How to make such constraint?
 private String captchaCode;

 ...
}

Eventually, how to inject request/session to form object so I can use my (custom) @FieldMatch JSR-303 annotation that forces two form fields to be equal.

The main problem is that even if we could inject session into custom constraint, object representing constraint is created only with first validation and then cached as singleton bean.

You could make your Validator spring managed with @Configurable .

The main problem is that [.. the] constraint is created only with first validation and then cached as singleton bean.

This would be a problem if the injected bean is not a scoped proxy . At least HttpServletRequest is such a proxy so you will find a safe way to your session.

You can create a custom annotation, let's call it @myVal , which compares the captcha session attribute and the text you enter in the form. This is how you can make such a thing:

@Constraint(validatedBy = CapVal.class)
@Target({METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER})
@Retention(RUNTIME)
public @interface MyVal {
    String message() default "Captcha is not correct!";
    Class<?>[] groups() default{};
    Class<? extends Payload>[] payload() default {}; 
}

and

public class CapVal implements ConstraintValidator<MyVal,String> {

    @Autowired
    HttpSession session;

    @Override
    public void initialize(MyVal myVal) {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if (s.compareToIgnoreCase(session.getAttribute("captcha_code").toString()) == 0) {
           return true;
        }
        return false;
    }
}

now put this @myVal annotation above 'captchaCode' field in the POJO and it's done

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM