mysql - 数据库的 Hibernate 加密对应用程序完全透明

标签 mysql database hibernate encryption grails

我正在处理一个 Grails 1.0.4 项目,该项目必须在不到 2 周内发布,而客户刚刚提出一个要求,即数据库中的所有数据都应该加密。

由于对应用程序本身中的每个数据库访问进行加密可能会花费大量时间并且容易出错,因此我寻求的解决方案是某种对应用程序透明的加密。

有没有办法设置 Hibernate 来加密所有表中的所有数据(可能除了 id 和 version 列)还是我应该寻求 MySQL 解决方案(我们使用的是 MySQL 5.0)?

编辑: 感谢您提供替代解决方案的所有帖子,如果客户改变主意,那就太好了。至于现在,要求是“数据库中没有纯文本”。

我想指出的第二件事是,我正在使用 Grails,对于那些不熟悉它的人来说,这是一种约定优于配置,因此即使是不符合约定的对应用程序的小改动也应避免。

最佳答案

如果您结束在应用程序中完成工作,您可以使用 Hibernate 自定义类型,它不会对您的代码添加那么多更改。

这是我使用过的加密字符串自定义类型:

import org.hibernate.usertype.UserType
import org.apache.log4j.Logger

import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.SQLException
import java.sql.Types

class EncryptedString implements UserType {

  // prefix category name with 'org.hibernate.type' to make logging of all types easier
  private final Logger _log = Logger.getLogger('org.hibernate.type.com.yourcompany.EncryptedString')

  Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws SQLException {
    String value = rs.getString(names[0])

    if (!value) {
      _log.trace "returning null as column: $names[0]"
      return null
    }

    _log.trace "returning '$value' as column: $names[0]"
    return CryptoUtils.decrypt(value)
  }

  void nullSafeSet(PreparedStatement st, Object value, int index) throws SQLException {
    if (value) {
      String encrypted = CryptoUtils.encrypt(value.toString())
      _log.trace "binding '$encrypted' to parameter: $index"
      st.setString index, encrypted
    }
    else {
      _log.trace "binding null to parameter: $index"
      st.setNull(index, Types.VARCHAR)
    }
  }

  Class<String> returnedClass() { String }

  int[] sqlTypes() { [Types.VARCHAR] as int[] }

  Object assemble(Serializable cached, Object owner) { cached.toString() }

  Object deepCopy(Object value) { value.toString() }

  Serializable disassemble(Object value) { value.toString() }

  boolean equals(Object x, Object y) { x == y }

  int hashCode(Object x) { x.hashCode() }

  boolean isMutable() { true }

  Object replace(Object original, Object target, Object owner) { original }
}

基于此,为 int、long 等创建类似的类应该很简单。要使用它,请将类型添加到映射闭包中:

class MyDomainClass {

  String name
  String otherField

  static mapping = {
    name type: EncryptedString
    otherField type: EncryptedString
  }
}

我省略了 CryptoUtils.encrypt() 和 CryptoUtils.decrypt() 方法,因为它们不是 Grails 特定的。我们正在使用 AES,例如“密码密码 = Cipher.getInstance('AES/CBC/PKCS5Padding')”。无论您最终使用什么,请确保它是双向加密,即不要使用 SHA-256。

关于mysql - 数据库的 Hibernate 加密对应用程序完全透明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1487439/

相关文章:

php - 如何在php中插入mysql数据以使用Buk Sms Api发送短信

android - 如何使用游标从数据库中检索数据? (安卓,SQLite)

mysql - 多列索引在 MySQL 中如何工作?

java - 多对多。配置级联,以便在删除端点实体时自动从中间表中删除数据

java - 如何在 Spring Source Tool 中添加 struts 或 hibernate 功能?

java - PersistenceException - 当多个 @OneToMany 关系与同一实体时抛出 org.hibernate.exception.ConstraintViolationException

mysql - 使用自连接子查询更新

php - 我可以使用 PHP 在 map 中设置时区吗?

mysql - 我想将所有这些表(学生、教师、类(class))链接到父表(类(class)),但我有错误?

MySql用户输入限制