2

我有一种使用休眠持久性和休眠验证的情况,虽然我已经想到了一些 hack-ish 方法,但我不知道使用休眠持久性和验证解决这个问题的最佳方法。

简单地说,我有一个 User 对象,我想保留它。但在我坚持之前,我想验证它。很标准的东西。

现在,一个用户对象有一个密码,我们有关于有效密码的规则。例如:最少 8 个字符,包括至少 1 个数字,等等……我想验证这些东西。

但是当我坚持时,我需要加密/加盐/散列密码。但是在我进行加盐/散列之后,显然没有合理的方法对密码进行上述验证。

所以,我想我可以为此使用@PrePersist 和@PreUpdate 注释。我的想法是在 User 类中我有一个名为 onCreate() 的方法。我用@PrePersist 对其进行了标记,然后我做了这样的事情(我对onUpdate()有类似的东西):

@PrePersist
protected void onCreate() {
    encryptPassword();
}

我认为当我调用 entityManager.persist() 时,它会首先调用验证,然后调用 onCreate() 然后持久化。因此,验证将验证原始的、未加盐/散列的密码。加盐/散列将在以后发生。

但是,当我运行测试和调试时,我发现标记有 @PrePersist 的方法在验证运行之前被调用,这意味着我无法再验证我的密码了。

如何正确地将密码的加盐/散列连接到 entityManager.persist() 生命周期中,以便我可以正确验证,然后在加盐和散列之后并最终持久化?

谢谢。

4

1 回答 1

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) {
        ...
    }
}

完毕。

于 2013-08-14T12:09:37.017 回答