我有使用hibernate持久性和hibernate验证的情况,虽然我已经想到了一些hack-ish方法,但我不知道使用hibernate持久性和验证来解决这个问题的最佳方法。
简单地说,我有一个User对象,我想坚持下去。但在我坚持之前,我想验证它。非常标准的东西。
现在,User对象有一个密码,我们有关于有效密码的规则。例如:最少8个字符,包括至少1个数字等...我想验证这些事情。
但是当我坚持下去时,我需要加密/加密/哈希密码。但是在我进行盐析/散列后,显然没有合理的方法对密码进行上述验证。
所以,我认为我可以使用@PrePersist和@PreUpdate注释。我的想法是在User类中我有一个名为onCreate()的方法。我用@PrePersist标记了它,我做了类似的事情(我对onUpdate()有类似的东西):
@PrePersist
protected void onCreate() {
encryptPassword();
}
我认为当我调用entityManager.persist()时,它首先调用验证,然后调用onCreate()然后继续。因此验证将验证原始的,非盐渍/哈希密码。盐腌/散列会在以后发生。
当我运行测试并进行调试时,我发现在验证运行之前调用标记为@PrePersist的方法意味着我无法再验证我的密码。
如何将密码的salting / hashing正确挂钩到entityManager.persist()生命周期中,以便我可以正确验证并在该salt和hash之后并最终持久化?
感谢。
答案 0 :(得分:1)
使用两个bean属性,一个用于持久性,另一个用于验证/转换。像这样:
@Entity
@MyCustomConstraint(...)
public class User implements Serializable {
// place persistence annotations here, for example
@Lob @Column(...)
private byte[] hashedPassword;
// place validation constraints here, for example
@Size(min = 8, max = 16)
@Transient
private String password;
public byte[] getHashedPassword() {
return this.hashedPassword;
}
protected void setHashedPassword(byte[] hashedPassword) {
this.hashedPassword = hashedPassword;
}
public void setPassword(String password) {
this.password = password;
this.setHashedPassword(this.hashAndSaltMyPassword(this.password));
}
protected String getPassword() {
return this.password;
}
protected byte[] hashAndSaltMyPassword(String password) {
...
}
}
完成。