基于 Spring session 的 javax 约束验证

标签 spring validation spring-mvc bean-validation

我想要完成的是在自定义约束中访问我的 Spring Session

示例场景:

自定义约束@UniqueEmail 验证电子邮件尚未在系统中使用。此验证在编辑端点上执行,如果用户没有更改电子邮件,则应忽略,第一:因为不需要它,第二:因为查询该电子邮件的数据库实际上会返回一个结果,即用户本身,尽管没有访问 session 就无法告诉它

这个作品:

如果我使用带有自定义编辑器的模型属性 @InitBinder 我可以在验证发生之前在要验证的 bean 中设置一个属性,就像这样

@InitBinder(value="myModelObj")
protected void initBinder(WebDataBinder binder, HttpSession session) {
    User user = (User) session.getAttribute("user");
    binder.registerCustomEditor(User.class, "user", new UidPropertyEditor(user));
}

@RequestMapping(...)
public String updateUser(@Valid @ModelAttribute("myModelObj") MyModelObj form){
    ...
}

MyModelObj 有一个属性,它将被实际 session 用户替换。问题:
  • bean 中必须有一个属性来保存用户,即使它不能通过 Web 表单编辑
  • Web 表单也必须提交此属性,在我的情况下使用 input[type="hidden"] 字段(用户可以随意更改它,我们从不相信用户发送的内容)

  • 这不起作用

    新端点必须使用@RequestBody 而不是@ModelAttribute,这意味着(afaik)@InitBinder 将不再工作,因此无法访问 session 对象。

    我如何(如果可能)从自定义约束中访问 session ?
    public class EmailIsUniqueStringValidator implements ConstraintValidator<EmailIsUnique, String> {
    
    @Autowired
    private UserDAO userDAO;
    
    HttpSession session; //Somehow initialized
    
    @Override
    public void boolean isValid(String email, ConstraintValidatorContext context) {
        User user = (User) session.getAttribute("user");
        if(user.getEmail().equals(email)){
            return true; // No need to validate
        }
        else if(userDAO.emailInUse(email)) {
            return false;
        }
    }
    

    非理想方法:

    我现在正在做的是在 Controller 中手动执行依赖于 session 的验证,这意味着我有 2 个执行验证的点。

    this post 中还有一些其他有趣的选项也是,但如果有办法访问 session ......

    提前致谢

    最佳答案

    这可以使用 RequestContextHolder 来实现像这样:

    public class EmailIsUniqueStringValidator implements ConstraintValidator<EmailIsUnique,         String> {
    
    @Autowired
    private UserDAO userDAO;
    
    HttpSession session;
    
    @Override
    public void boolean isValid(String email, ConstraintValidatorContext context) {
        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        session = attr.getRequest().getSession();
    
        User user = (User) session.getAttribute("user");
        if(user.getEmail().equals(email)){
            return true; // No need to validate
        }
        else if(userDAO.emailInUse(email)) {
            return false;
        }
    }
    

    关于基于 Spring session 的 javax 约束验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20054121/

    相关文章:

    java - 如何使用 @RestController 以纯文本形式返回简单的 boolean 值?

    spring - 如何让 Spring Batch 在一段时间后重试失败的步骤?

    spring - 在不创建上下文的情况下禁用 Spring 和 Junit5 测试

    部分 View 中的 ValidationSummary 未显示错误

    java - Spring Security登录返回404

    java - HttpClient 中的 setMaxTotal 和 setDefaultMaxPerRoute?

    asp.net-mvc - AddImplicitRequiredAttributeForValueTypes 如何真正起作用以及它的用途是什么?

    javascript - 验证复选框限制javascript

    java - ClassPathXmlApplicationContext 找不到 xml 文件

    java - 被拒绝的 bean 名称 'propertyConfigurer' : no URL paths identified