2

我们需要在使用 JPA 存储字符串时对其进行加密,并在读取时对其进行解密。首先,我们不能使用一些休眠配置或任何其他配置文件,因为我们的属性是通用的。这意味着我们的属性看起来像这样(简单地说,我们已经在这里实现了一些处理):

@Entity
@Table(name = "PROPERTY")
@Access(AccessType.FIELD)
public class Property implements Serializable
{
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "PRO_ID")
    private long id;

    @Version
    @Temporal(value = TemporalType.TIMESTAMP)
    @Column(name = "PRO_VERSION")
    private Date version;

    @Column(name = "PRO_KEY")
    private String key;

    @Transient
    private String value;

    @Column(name = "PRO_ENCRYPTED")
    private boolean encrypted = false;

    public long getId()
    {
        return id;
    }

    public void setId(long id)
    {
        this.id = id;
    }

    public Date getVersion()
    {
        return version;
    }

    public void setVersion(Date version)
    {
        this.version = version;
    }

    public String getKey()
    {
        return key;
    }

    public void setKey(String key)
    {
        this.key = key;
    }

    public String getValue()
    {
        return value;
    }

    public void setValue(String value)
    {
        this.value = value;
    }

    public boolean isEncrypted()
    {
        return encrypted;
    }

    public void setEncrypted(boolean encrypted)
    {
        this.encrypted = encrypted;
    }

    @Access(AccessType.PROPERTY)
    @Column(name = "PRO_VALUE")
    protected String getValueDatabase()
    {
        // TODO: add decryption
        return value;
    }

    protected void setValueDatabase(String value)
    {
        // TODO: add encryption
        this.value = value;
    }
}

(我们可以使用 isEncrypted() 方法区分哪些属性必须加密。根据属性设置为 true 或 false)。Out Encryptor 类(简化)与 Jasypt 一起使用:

public final class MyEncrypter
{
    private static final String password = "AHKG@a4SjHH5%j%974";
    private static final StandardPBEStringEncryptor encryptor;

    static 
    {
        encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword(password);
    }

    public final static String encrypt(String string)
    {
           return encryptor.encrypt(string);
    }

        public final static String decrypt(String encrypted)
        {
            return encryptor.decrypt(encrypted);
        }
}

加密/解密有效。实际上,我们的整个持久性处理都有效。我们可以保存加密数据。但是,当我们读取加密数据时,我们得到以下信息:

javax.persistence.OptimisticLockException: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [at.jit.remind.jee.domain.context.model.Property#10]

奇怪的是,只有当且仅当 Hibernates 尝试更新加密文本时,才会发生这种情况。但它不会发生,当我们伪加密和伪解密我们的文本时。这意味着我们反转文本,用 Hibernate 存储反转的文本,并在 Hibernate 尝试更新它时“解密”它。所以我们的整个处理工作正常,但是当我们使用“真正的”加密时它不起作用的原因是什么?有任何想法吗?

(同样,en- 和 decryption 本身有效。我让它在不同的 JUnit 类中运行以确保这一点。)

4

2 回答 2

1

我们决定使用另一种加密,因为显然 jasypt 对 Hibernate 做了一些奇怪的事情。似乎这种加密/解密以某种方式为 Hibernate 产生了一个“脏标志”,因此 Hibernate 尝试更新数据库条目,尽管加密同时更改了值。不可能隔离它。

于 2012-02-01T19:04:19.077 回答
0

这是因为您的对象仍附加到休眠会话,并且其内部状态已更改。尝试首先调用 session.evict(object) 然后更改要加密的文本。

于 2012-02-01T13:31:23.263 回答