我们需要在使用 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 类中运行以确保这一点。)