使用JPA将哈希值存储为字节数组

6

我的User实体类包含一个密码哈希字段,它是一个具有固定长度的字节数组(32字节,因为它是SHA-256哈希)。

@Entity
public class User {
    @Column(nullable=false)
    private byte[] passwordHash;
    ...
}

如您所见,我没有使用任何特殊的注释,只是一个 NOT NULL。

这个方法是可行的,但它是否能够高效运行呢?我的架构是由Hibernate生成的,但我不知道它确切地生成了什么(我目前正在使用内存中的HSQL数据库)。

我担心,由于它不知道这是一个固定长度的数组(Column注释中的length字段仅适用于字符串),它将把此哈希存储在BLOB字段中,并作为指针添加到记录中(如果我正确理解数据库的工作原理)。

这是真的吗?我该如何更改它?我应该将哈希编码为字符串,使用base64或hex,接受那种小的性能/正确性影响吗?


为什么不尝试使用实际的目标数据库,看看它会生成什么呢? - skaffman
@skaffman:我已经将数据库更改为MySQL,并生成了一个TINYBLOB列。 - Bart van Heukelom
虽然我想这并不是真正重要的。我永远不会按密码哈希值进行索引,而且我每次只需要读取一个记录。但出于学术目的,我仍然对使其完美感兴趣。 - Bart van Heukelom
4个回答

5
我担心的是,由于它不知道它是一个固定长度的数组(Column注释中的长度字段仅适用于字符串),(...)
如果您指定了列长度,Hibernate将使用此信息来确定要生成的SQL列类型(TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB)。
我需要的是BINARY(32)
你试过这个吗?
@Column(columnDefinition="BINARY(32) NOT NULL")
private byte[] passwordHash;

1

tinyblob是一个不错的选择(mysql类型参考),但我的所有应用都可以使用Strings正常工作。 如果你真的关心毫秒,请在分析器中尝试两个版本并查看哪个效果最好。 我偏爱的分析器是netbeans中包含的分析器。


0
据我所知,SHA-256哈希始终只包含可打印字符(如果不是,则使用base64进行编码),因此解决方案是可以将其存储为字符串,然后使用Column注释的length字段。这样你就有了固定的长度,并且不用担心性能问题。

1
不,我已经看到输出结果了,它主要由不可打印的字符组成(或者根本不是字符数据)。当然,我可以使用base64或十六进制编码,但如果我能以纯二进制形式存储它,那就太好了。 - Bart van Heukelom

0

虽然效率可能不如其他方法高,但我建议您使用String作为存储类型,并在需要时使用getter和setter方法进行翻译。这样可以实现JPA在不同数据库之间的最大可移植性。

我在处理日期/时间时也使用类似的技术,通过存储自纪元以来的UTC时间戳来避免时区问题(时区信息在所有数据库中的日期中都不可移植)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接