12

当从支持休眠的 web 应用程序传递时,我有一个需要加密的数据库列。webapp 在 tomcat 6、Hibernate 4 和 Mysql 上作为后备存储。

然而问题是加密/解密该字段的密码仅在程序运行时可用。最初我希望使用 AES_ENCRYPT/DECRYPT 方法,这里概述得很好:

Hibernate 中的数据库加密

和这里:

http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/mapping.html#mapping-column-read-and-write

(虽然这确实指的是 3.6 版的 hibernate,但我相信它在 4.0 中应该是相同的)。

但是,由于这使用以下表示法:

@Column(columnDefinition= "LONGBLOB", name="encryptedBody") 
@ColumnTransformer(
  read="AES_DECRYPT(encryptedBody, 'password')", 
  write="AES_ENCRYPT(?, 'password')")
public byte[]  getEncryptedBody() {
    return encryptedBody;
}

public void setEncryptedBody(byte[]  encryptedBody) {
    this.encryptedBody = encryptedBody;
}

这要求在注释本身中指定密码,并且不能是变量。

有没有办法以这种方式通过休眠使用数据库方法,但将密码作为变量?有更好的方法吗?

4

2 回答 2

3

目前没有一种方法可以参数化读/写片段的片段。它们更多地是作为通用解决方案。我们已经讨论了在 Hibernate 中添加对 @Encrypted 的支持,这大致就像您建议的那样。@Encrypted 将提供更大的灵活性,例如 in-vm 加密与 in-db 加密、参数化等。

JPA 2.1 还有一个您可以使用的特性,称为属性转换器。然而,他们只能应用 in-vm 加密。

于 2013-06-04T14:22:56.547 回答
0

您可以使用 Hibernate @Type 属性,根据您的要求,您可以自定义注释并在字段之上应用。喜欢 :

  public class PhoneNumberType implements UserType {
  @Override
  public int[] sqlTypes() {
return new int[]{Types.INTEGER, Types.INTEGER, Types.INTEGER};
  }

  @Override
  public Class returnedClass() {
      return PhoneNumber.class;
  }

  // other methods
  }   

一、空SafeGet方法:

  @Override
  public Object nullSafeGet(ResultSet rs, String[] names, 
  SharedSessionContractImplementor session, Object owner) throws HibernateException,                   
    SQLException {
  int countryCode = rs.getInt(names[0]);
   if (rs.wasNull())
      return null;
   int cityCode = rs.getInt(names[1]);
  int number = rs.getInt(names[2]);
  PhoneNumber employeeNumber = new PhoneNumber(countryCode, cityCode, number);
   return employeeNumber;
   }

接下来,null SafeSet 方法:

  @Override
   public void nullSafeSet(PreparedStatement st, Object value, 
    int index, SharedSessionContractImplementor session) 
     throws HibernateException, SQLException {
      if (Objects.isNull(value)) {
      st.setNull(index, Types.INTEGER);
      } else {
      PhoneNumber employeeNumber = (PhoneNumber) value;
      st.setInt(index,employeeNumber.getCountryCode());
      st.setInt(index+1,employeeNumber.getCityCode());
      st.setInt(index+2,employeeNumber.getNumber());
    }
   }

最后,我们可以在我们的 OfficeEmployee 实体类中声明我们自定义的 PhoneNumberType:

  @Entity
  @Table(name = "OfficeEmployee")
   public class OfficeEmployee {

    @Columns(columns = { @Column(name = "country_code"), 
    @Column(name = "city_code"), @Column(name = "number") })
    @Type(type = "com.baeldung.hibernate.customtypes.PhoneNumberType")
     private PhoneNumber employeeNumber;

   // other fields and methods
    }

这可能会解决您的问题,这将适用于所有数据库。如果您想了解更多信息,请参考 :: https://www.baeldung.com/hibernate-custom-types
同样您必须执行 UTF-8 编码/解码和 ISO-8859-1 解码/编码

于 2020-01-29T07:08:37.630 回答