我有一个数据库表,其中包含需要通过Hibernate读取和写入的字段。它是字符串字段,但内容是加密的。由于各种原因(例如需要对纯文本值进行排序),加密/解密功能在数据库内而不是Java中实现。在休眠中自动应用字段转换功能
我现在正在努力的问题是找到一种方法来调用Hibernate生成的SQL中的加密/解密函数,无论该字段是否被引用,并且对我的应用程序代码都是透明的。这可能吗?我研究了Hibernate对“派生”属性的支持,但不幸的是,这种方法不支持读写字段。任何想法赞赏。
我有一个数据库表,其中包含需要通过Hibernate读取和写入的字段。它是字符串字段,但内容是加密的。由于各种原因(例如需要对纯文本值进行排序),加密/解密功能在数据库内而不是Java中实现。在休眠中自动应用字段转换功能
我现在正在努力的问题是找到一种方法来调用Hibernate生成的SQL中的加密/解密函数,无论该字段是否被引用,并且对我的应用程序代码都是透明的。这可能吗?我研究了Hibernate对“派生”属性的支持,但不幸的是,这种方法不支持读写字段。任何想法赞赏。
事实上,最后我走了一条不同的路线,并向Hibernate提交了patch。它在上周承诺上线,因此我认为它将在3.5之后的下一个版本中发布。现在,在属性映射中,可以指定SQL“读取”和“写入”表达式来调用SQL函数或执行其他类型的数据库端转换。
假设你可以访问加密/从Java内部解密算法,我会成立我的映射类像
public class encryptedTable {
@Column(name="encrypted_field")
private String encryptedValue;
@Transient
private String value;
public String getEncryptedValue() {
return encryptedValue;
}
public String getValue() {
return value;
}
public void setEncryptedValue(String encryptedValue) {
this.encryptedValue = encryptedValue;
this.value = decrypt(encryptedValue);
}
public void setValue(String value) {
this.value = value;
this.encryptedValue = encrypt(value);
}
}
然后用获取/设置值作为访问你的程序中,离开获取/设置访问数据库时Hibernates使用的EncryptedValue。
这并没有解决我希望Hibernate在查询中引用该字段(例如用于排序)时自动调用数据库的解密函数的愿望。 – 2009-07-30 15:20:05
您可以在数据库中有一个触发器,它在检索时解密该值并替换返回的结果,并在插入时对该值进行加密并将存储的结果替换为加密值。您也可以使用视图封装器来执行此操作 - 即在视图上具有插入触发器,并让视图自动解密该值。
为了更好地解释:有一个解密值的视图,以及一个开启插入触发器来加密链接到视图的值。
我曾经考虑过这样的事情,但由于我有几张带有加密字段的表,并且我依靠Hibernate来自动生成模式,所以我认为它太难维护了。但也许有一种方法可以动态生成视图和触发器。嗯... – 2009-07-30 17:40:30
我们使用类似的方法,但我们有我们的数据库生成,然后我们逆向工程。如果要从对象安装数据库,则可以将视图/触发器的模式作为单独的一部分,然后将其作为安装脚本/执行的一部分安装。 – aperkins 2009-07-30 18:50:45
我不认为有一种方法可以像你所描述的那样进行加密,对您的应用程序来说透明的完全是。最接近的事情是让它在实体之外透明。在你的实体类:
@Entity
@SQLInsert(sql="INSERT INTO my_table(my_column, id) VALUES(encrypt(?),?)")
@SQLUpdate(sql="UPDATE my_table SET my_column = encrypt(?) WHERE id = ?")
public class MyEntity {
private String myValue;
....
@Formula("decrypt(my_column)")
public String getValue() {
return myValue;
}
public void setValue(String value) {
myValue = value;
}
@Column (name="my_column")
private String getValueCopy() {
return myValue;
}
private void setValueCopy(String value) {
}
}
value
被映射为派生属性,你应该能够在查询中使用它。
valueCopy
是私有的,用于绕过只读的派生属性。
SQLInsert
和SQLUpdate
是黑巫术魔法强制加密插入/更新。请注意,参数顺序很重要,您需要找出Hibernate在不使用自定义插入/更新的情况下生成参数的顺序,然后复制它。
为什么不直接使用SQl服务器加密,它似乎已经通过调用Hibernate中的存储过程而不是让Hibernate生成查询?
你能澄清`排列纯文本位吗?这是否意味着你正在做`SELECT my_field FROM my_table ORDER BY decrypt(my_field)`? – ChssPly76 2009-07-30 16:45:10
是的,但更像SELECT解密(my_field)FROM my_table ORDER BY解密(my_field)。无论如何,这就是一个例子。我还需要执行不区分大小写的搜索(对解密值调用UPPER)以及使用LIKE运算符进行部分字符串匹配。所有这些都要求数据库能够进行解密。 – 2009-07-30 17:43:43