如何使用Hibernate映射byte []属性?

时间:2012-05-14 21:02:12

标签: java string hibernate encoding sha1

我正在使用Hibernate / Java将实体持久化到数据库。该实体具有密码字段,该字段是字符串。在我的应用程序中注册用户时,我使用SHA-1哈希密码(我承认这有点弱)。这会生成 byte [] ,然后我将其转换为 String    new String(byte[] arr); 每当我想要记录用户时,我只需从数据库中检索哈希密码(如 String ),并在登录时将其与输入密码的摘要进行比较    hashedPasswordFromDatabase.equals(SHA1_HASH(inputPassword));

这在我的开发系统(Windows 7,JDK 1.6.0_23 / JDK 1.7,MySQL 5.5,Tomcat 6.0.26)上运行完美,但是在我们的服务器上部署它(在Linux上运行JDK 1.6) ),即使对于相同的密码, equals 方法永远不会评估为TRUE。我快速设置了一个新的开发系统(Ubuntu 12.04,MySQL 5.5,JDK 1.7.0_03,Tomcat 7.0.22),它也不能在那里工作。

我知道 String 类的Java API文档中可能存在的编码问题,并且在SO的几个地方也有说明。我在这个论坛上尝试了几种编码(例如Base64,Latin-1),最后我得到了 UnsupportedEncodingException 。我想我最好避免String转换。那么我如何设计我的数据库,以便Hibernate生成的实体类为密码字段而不是字符串提供 byte []

3 个答案:

答案 0 :(得分:5)

是的,问题最有可能发生在byte[]String转化中。您必须知道SHA生成原始byte数组,并且无法保证任意byte[]将生成有效String,无论编码如何。因此,您的代码只是偶然

完全避免这个问题:

  • 在BLOB中存储原始byte[] - 最安全,最有效的存储方式。在Hibernate中,只需在POJO上使用byte[]属性。

  • 使用编码byte[](请查看Decode Base64 data in Java)并将其存储为字符串。

BTW remember about salting

答案 1 :(得分:1)

就我而言,糟糕的数据库设计促使我在Clob的情况下使用Blob。解决方案是使用Lob注释对属性进行休眠,并将另一个属性放在String类型中。

在代码的其他级别,当我调用get或set时,我使用String属性和这个,获取或设置字节数组值。

@Entity
@Table(name = "CMUN_TAGS")
@SequenceGenerator(name = "idSeqTag", sequenceName = "SEQ_CMUN_TAGS")
public class CmunTagsDO implements java.io.Serializable {
  private BigDecimal lngIdTag;
  private byte[] blobValTag;
  private String strValTag;

  @Id
  @Column(name = "LNG_ID_TAG", unique = true, nullable = false, precision = 20, scale = 0)
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idSeqTag")
  public BigDecimal getLngIdTag() {
    return this.lngIdTag;
  }

  public void setLngIdTag(BigDecimal lngIdTag) {
    this.lngIdTag = lngIdTag;
  }

  @Column(name = "BLOB_VAL_TAG", nullable = false)
  @Lob
  public byte[] getBlobValTag() {
    return this.blobValTag;
  }

  public void setBlobValTag(byte[] blobValTag) {
    this.blobValorTag = blobValorTag;
  }

  @Transient
  public String getStrValTag() {
    strValTag = new String(getBlobValTag());
    return strValTag;
  }

  public void setStrValTag(String strValTag) {
    setBlobValTag(strValTag.getBytes());
    this.strValTag = strValTag;
  }
}

答案 2 :(得分:0)

您可以将字节转换为十六进制表示形式,如下所示:

public String encryptPassword(String passwordInClear) {
            // Salt all you want here.
            MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
    byte[] digest = sha256.digest(passwordInClear.getBytes());
    return digestToString(digest);
}

private String digestToString(byte[] digest) {
    StringBuilder hashString = new StringBuilder();
    for (int i = 0; i < digest.length; i++) {
        String hex = Integer.toHexString(digest[i]);
        if (hex.length() == 1) {
            hashString.append('0');
            hashString.append(hex.charAt(hex.length() - 1));
        } else {
            hashString.append(hex.substring(hex.length() - 2));
        }
    }
    return hashString.toString();
}