【问题标题】:Is it possible to make my custom validation annotation to be ignored on persist?是否可以在持久化时忽略我的自定义验证注释?
【发布时间】:2017-06-14 13:25:40
【问题描述】:

我使用 Spring 4 和 Hibernate 5

我有带有自定义验证器的密码字段的用户类。

我需要验证它,同时表单绑定长度为 8 个字符,包括小写和大写字母以及数字。

当用户输入密码时它是有效的,但是当我编码它时它是无效的。

那么有没有办法让我的自定义验证注释在持久化时被忽略?

我知道我可以为未加密的密码创建不同的字段,或者创建数据传输对象,对其进行验证,然后将其数据传递给用户。 但我对注释参数化的可能性感兴趣。

@Entity
@Table(name = "user")
public class User { 
//other fields

@NotNull
@NotEmpty
@ValidPassword
@Column(name = "password", nullable = false, length = 60)
private String password;
//getters and setters 
}

我的验证者

@Target({ TYPE, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = PasswordValidator.class)
@Documented
public @interface ValidPassword {
String message() default "Password is too short! Must be 8 digits and    include lowercase, uppercase letters and numbers.";

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};
}

和

public class PasswordValidator implements ConstraintValidator<ValidPassword, String> {

private Pattern pattern;
private Matcher matcher;
private static final String PATTERN = "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,})";

@Override
public void initialize(ValidPassword constraintAnnotation) {
}

@Override
public boolean isValid(String password, ConstraintValidatorContext context) {
    return (validate(password));
}

private boolean validate(String password) {
    pattern = Pattern.compile(PATTERN);
    matcher = pattern.matcher(password);
    return matcher.matches();
}
}

控制器方法

@RequestMapping(value = "/registeruser", method = RequestMethod.POST)
public String registerUser(@ModelAttribute("user") @Valid User user, BindingResult result, Model model) {
    if (result.hasErrors()) {
        model.addAttribute("errorSummary", result.getFieldErrors().stream()
                .map(e -> e.getField() + " error - " + e.getDefaultMessage() + " ").collect(Collectors.toList()));
        model.addAttribute("user", user);

    } else {
        User registered = null;
        registered = createUserAccount(user, result);

        if (registered == null) {
            model.addAttribute("errorSummary", "User with this email already registered!");
            model.addAttribute("user", user);
            return "registration";
        }
        model.addAttribute("flashMessage", "User registered successfully!");
    }

    return "registration";
}

UserService 实现方法(我编码密码的地方)

@Transactional
@Override
public User registerNewUserAccount(User user) throws EmailExistsException {

    if (emailExist(user.getEmail())) {
        throw new EmailExistsException("There is an account with that email address:" + user.getEmail());
    }

    if (user.getPassword() == null) {
        user.setPassword(new BigInteger(130, new SecureRandom()).toString(32));
        System.out.println("+++++++++++++++" + user.getPassword());
    }
    user.setPassword(passwordEncoder.encode(user.getPassword()));
    user.setUserRole(new HashSet<UserRole>(1));
    user.getUserRole().add(new UserRole(user, Constants.RoleType.USER.name()));
    save(user);
    return user;
}

【问题讨论】:

  • Waht “在我对其进行编码时无效”,确切地说,您在代码中的哪个位置收到该错误?
  • 我在一个月前遇到过这样的情况,当时我只想在持久化上运行验证。见:stackoverflow.com/questions/43964065/…。您必须将验证设置为在“javax.persistence.validation.group.pre-update”(可能还有“javax.persistence.validation.group.pre-remove”)期间执行。在此处查看完整文档:docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/…
  • @zaph 当用户输入正确密码时有 8 位数字等等,当我用passwordEncoder.encode(user.getPassword()) 对其进行编码时,它现在变得更长了(例如:$2a$10$3/ufbdU3qMnn7e3IQ7hkjubrdRJrD7kKieAqflKEDvZ8b7DY8eUcu),所以验证失败
  • @TomerA 我需要对表单绑定进行验证,而不是坚持与您想要的相反
  • 通过对密码应用相同的函数并验证结果是否与数据库条目相同来验证密码。她的序言$2a$10$ 是关于它是如何生成的信息。

标签: java spring hibernate validation persistence


【解决方案1】:

默认情况下,所有约束都会进行验证。或者你可以指定Grouping Constraints

您可以通过创建界面来创建群组:

interface FormValidationGroup{}

并像这样注释password 字段:

@ValidPassword(groups = FormValidationGroup.class)
private String password;

Custom Constraints annotations 的文档,其中提到了 groups 参数。

Hibernate Validator 现在应该忽略 password 字段,除非您指定要验证的组。为了指定一个组来验证 Spring MVC 处理程序方法的参数,请使用 Validated 注释而不是 Valid。例如:

String registerUser(@ModelAttribute @Validated(FormValidationGroup.class) User user,
        BindingResult result, Model model) {
    if (result.hasErrors()) {

【讨论】:

  • 这很有用。但是我怎样才能让我的自定义组在表单绑定上得到验证,所以我可以使用 BindingResult hasErrors() 方法?
  • 我更新了我的答案以展示如何将自定义组与 Spring MVC 和BindingResult一起使用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-02
相关资源
最近更新 更多