我正在为一个项目开发一些RESTFull web服务。我使用Spring框架并使用gradle进行构建。问题是,我想在读写数据时对数据表进行加密和解密。我已经有一个算法(类)来加密和解密数据与AES等。我需要的是,如何注释这个方法到hibernate实体类,我需要为这个类创建bean吗?
例如:-
@Column(columnDefinition= "LONGBLOB", name = "card_no")
@ColumnTransformer(
read="decrypt(card_no)",
write="encrypt(?)")
private String cardNo;像这样,我想在这里添加我自己的加密/解密java方法。
发布于 2015-12-14 13:43:16
如果您能够使用JPA2.1,我建议在AttributeConverter实现中使用@Convert注释。
AttributeConverter定义了实体属性在序列化到数据存储时和从数据存储反序列化时的状态之间的协定。
public class CreditCard {
@Convert(converter = CreditCardNumberConverter.class)
private String creditCardNumber;
}您的转换器实现可能如下所示
public class CreditCardNumberConverter implements AttributeConverter<String, String> {
@Override
public String convertToDatabaseColumn(String attribute) {
/* perform encryption here */
}
@Override
public String convertToEntityAttribute(String dbData) {
/* perform decryption here */
}
}如果您不能利用JPA2.1,那么可以使用EntityListener或使用@PrePersist、@PreUpdate和@PostLoad来执行类似的逻辑来加密和解密数据库值。
如果您决定使用EntityListener或任何Pre/Post回调方法注释,请确保将解密结果存储在一个瞬态字段中,并将该字段用作您的业务层,如下所示:
public class CreditCard {
// this field could have package private get/set methods
@Column(name = "card_number", length = 25, nullable = false)
private String encrpytedCardNumber;
// this is the public operated upon field
@Transient
private String cardNumber;
@PostLoad
public void decryptCardNumber() {
// decrypts card number during DATABASE READ
this.cardNumber = EncryptionUtils.decrypt(encryptedCardNumber);
}
@PrePersist
@PreUpdate
public void encryptCardNumber() {
// encrypts card number during INSERT/UPDATE
this.encryptedCardNumber = EncryptionUtils.encrypt(cardNumber);
}
}这样做可以使对象中的实体状态与数据库中存在的内容保持一致,而不会让Hibernate认为实体在加载数据库数据后立即发生了变化。
发布于 2015-12-14 12:53:18
您可以通过几种方式来完成此操作。
使用JPA Listeners的
下面是一个简单的例子。请做相应的修改。
public class CustomListener{
@Inject
private EncryptorBean encryptor;
@PostLoad
@PostUpdate
public void decrypt(Object pc) {
if (!(pc instanceof)) {
return;
}
MyObj obj = (MyObj) pc;
if (obj.getCardNo() != null) {
obj.setCardNo(
encryptor.decryptString(user.getEncryptedCardNo);
}
}
@PrePersist
@PreUpdate
public void encrypt(Object pc) {
if (!(pc instanceof MyObj)) {
return;
}
MyObj obj = (MyObj ) pc;
if (obj.getCardNo() != null) {
user.setEncryptedCardNo(
encryptor.encryptString(user.getCardNo());
}
}
}使用这种方法时,您可能需要采取一些预防措施,以避免加密已经加密的cardNo值。无论cardNo是否已经加密,都可以使用一个附加的Transient属性来保存状态。
实体或简单地在
public String getCardNo(){ return EncrypUtil.decrypt( this.cardNo );} public void setCardNo(String cardNo){ this.cardNo= EncrypUtil.encrypt(cardNo);}
HibernateInterceptors公共类CustomInterceptor扩展EmptyInterceptor{公共布尔onSave(对象实体,可序列化id,Object[]状态,String[] propertyNames,Type[]类型)抛出CallbackException { if ( entity instanceof MyObj){ //检查是否已加密。//(瞬态属性可能很有用) entity.setCardNo(EncrypUtils.encrypt(entity.getCardNo()));}
@Convert注释并指定转换器@Convert(converter = CCConverter.class)私有字符串creditCardNumber;
应该是AttributeConverter的实现的CCConverter类
希望这能有所帮助。
https://stackoverflow.com/questions/34259457
复制相似问题