我做了一个SpringBoot应用程序,现在我在登录部分。 我使用自定义注释进行了一些自定义限制。 问题是,此自定义注释在密码被加密后应用于用户。
这是密码约束
public class PasswordConstraintValidator implements ConstraintValidator<ValidPassword, User>{
@Override
public void initialize(final ValidPassword arg0){}
@SneakyThrows
@Override
public boolean isValid(User user, ConstraintValidatorContext context) {
Properties props = new Properties();
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("passay.properties");
props.load(inputStream);
MessageResolver resolver = new PropertiesMessageResolver(props);
PasswordValidator validator = new PasswordValidator(resolver, Arrays.asList(
new LengthRule(8, 16),
new CharacterRule(EnglishCharacterData.UpperCase, 1),
new CharacterRule(EnglishCharacterData.LowerCase, 1),
new CharacterRule(EnglishCharacterData.Digit, 1),
new CharacterRule(EnglishCharacterData.Special, 1),
new WhitespaceRule(),
new IllegalSequenceRule(EnglishSequenceData.Alphabetical, 5, false),
new IllegalSequenceRule(EnglishSequenceData.Numerical, 5, false)
));
RuleResult result = validator.validate(new PasswordData(user.getPasswordHash()));
if (result.isValid()) {
return true;
}
List<String> messages = validator.getMessages(result);
String messageTemplate = String.join(",", messages);
context.buildConstraintViolationWithTemplate(messageTemplate)
.addConstraintViolation()
.disableDefaultConstraintViolation();
return false;
}
}
这是我加密密码的地方
@Qualifier("getPasswordEncoder")
@Autowired
private PasswordEncoder passwordEncoder;
public void registerNewUserAccount(User user){
Optional<User> userOptional= userRepository.findUserByEmailAddress(user.getEmailAddress());
if(userOptional.isPresent()){
throw new IllegalStateException("email taken!");
}
// Se comenteaza pentru ca: Validarea parolei se face pe hashPassword
//Dupa rezolvarea problemei, se decomenteaza
user.setPasswordHash(passwordEncoder.encode(user.getPasswordHash()));
user.setEnabled(false);
Optional<User> saved = Optional.of(user);
saved.ifPresent(u -> {
try {
String token = UUID.randomUUID().toString();
verificationTokenService.save(user, token);
try {
emailService.sendHtmlMail(u);
} catch (MessagingException e) {
e.printStackTrace();
}
} catch (Exception e){
e.printStackTrace();
}
});
userRepository.save(user);
System.out.println(user);
saved.get();
}
这是用户:
@Entity
@Table
@ValidPassword
public class User implements UserDetails {
@Id
@SequenceGenerator( //se auto-incrementeaza pkul ?
name = "user_sequence",
sequenceName = "user_sequence",
allocationSize = 1
)
@GeneratedValue( ///??????????
strategy = GenerationType.SEQUENCE,//maybe auto if not working
generator = "user_sequence"
)
//TODO Change camelCase to python_format
private Long id;
private String userName;
@NonNull
@NotBlank(message = "New password is mandatory")
private String passwordHash;
private String firstName;
private String lastName;
private String phoneNumber;
@Email
private String emailAddress;
public String address1;
public String address2;
private String city;
private String country;
private String zipcode;
private boolean enabled;
这里的问题是,当您将实体保存到数据库时,还会检查验证注释,然后触发ConstraintViolationException
。
因此,最好的方法是遵循数据传输对象模式。我建议您创建一个新类,例如UserDto
该类将类似于User
实体,甚至是实体的副本,理想情况下,您的UserDto
类应仅包含控制器所需的字段,包括所有必要的验证注释。
在加密密码的service
类中,在保存用户之前,将UserDto
实例转换为User
实体,但请记住从 User 实体中删除@ValidPassword
批注,因为你不想验证加密的密码,并且已经检查了 UserDto 类的验证
请记住:UserDto
不应该是一个实体类,因为我们不希望它在数据库中,我们只需要它用于验证目的。