GlassFish SHA-256 摘要身份验证
出于开发目的,我一直以纯文本形式存储密码,但想开始存储哈希值,但由于出现以下 SecurityException,到目前为止尚未成功让 GlassFish 针对哈希密码进行正确身份验证:
SEVERE: jdbcrealm.invaliduserreason
WARNING: WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Security Exception
首先,我正在运行GlassFish 3.1 并将我的 JDBC 领域的摘要设置为 SHA-256。
我的 User
类具有以下带注释的密码字段:
@Basic(fetch = FetchType.LAZY)
@Column(length = 45, nullable = false)
private String password;
以下帮助器方法负责对密码进行哈希处理:
private byte[] digest(String input) {
byte[] output = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
output = md.digest(input.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(RegistrationController.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(RegistrationController.class.getName()).log(Level.SEVERE, null, ex);
}
return output;
}
然后我按如下方式设置用户的密码:
u.setPassword(Base64.encode(digest(password)).toString());
我不会对 Base64 进行编码,因为这似乎没有记录,但这个问题:Glassfish 安全 - jdbcRealm:如何使用 SHA 配置登录 - 256摘要建议您确实需要这样做。
所以我想我想知道的是,GlassFish 是否期望 String (VARCHAR) 或 byte[] (BLOB) 作为数据库中的密码字段,我是否正确地散列密码,以及附加 Base64 编码是否正确密码哈希?
谢谢!
I have been storing my passwords in plain-text for development purposes but want to start storing the hashes instead, but have so far not yet succeeded in having GlassFish properly authenticate against a hashed password due to the following SecurityException:
SEVERE: jdbcrealm.invaliduserreason
WARNING: WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Security Exception
First off, I am running GlassFish 3.1 and have setup the digest for my JDBC realm to SHA-256.
My User
class has the following annotated password field:
@Basic(fetch = FetchType.LAZY)
@Column(length = 45, nullable = false)
private String password;
The following helper method is responsible for hashing the password:
private byte[] digest(String input) {
byte[] output = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
output = md.digest(input.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(RegistrationController.class.getName()).log(Level.SEVERE, null, ex);
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(RegistrationController.class.getName()).log(Level.SEVERE, null, ex);
}
return output;
}
I then set the password on the user as follows:
u.setPassword(Base64.encode(digest(password)).toString());
I wouldn't have Base64 encoded the because this seems to be undocumented but this question: Glassfish Security - jdbcRealm: How to configure login with SHA-256 digest suggests you do need to do so.
So I guess what I would like to know is, does GlassFish expect a String (VARCHAR) or a byte[] (BLOB) as the password field in the database, am I correctly hashing the password, and is it correct to additionally Base64 encode the password hash?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
它需要一个映射到 JDBC 中的 Java 类型 java.lang.String 的列,这些列通常是 CHAR、VARCHAR 等。LOB 将无法工作,因为 JDBC 领域实现会发出 ResultSet .getString 方法调用调用来获取密码哈希值。
Base64 编码不是唯一受支持的选项。您也可以执行十六进制编码。但您必须执行其中任何一个,并将 JDBC 领域配置为在运行时执行相同的操作。如果没有编码参数,Glassfish 会将与摘要关联的字节序列转换为为领域配置的
charset
中的字符序列。我怀疑这个问题与表达式
input.getBytes("UTF-8")
中提到的 UTF-8 编码有关。值得验证digest
方法提供的结果的 Base64 编码是否确实与数据库中存储的密码哈希相匹配。另外,考虑到失败的原因是
jdbcrealm.invaliduserreason
,我还怀疑以下条件之一可能为真:base64
或hex
之一(大小写并不重要,根据 JDBC 领域的源代码),否则您最终会遇到以下情况:摘要字节数组被转换为字符数组(在我看来,这有点不稳定,除非你能保证用户提供的密码始终采用特定的编码)。derby.properties
的文件放置在 Derby 数据库的位置,其属性为derby.language.logStatementText=true
其中。关闭数据库时,derby.log 文件将填充应用程序服务器发出的所有查询。It expects a column that maps to the Java Type
java.lang.String
in JDBC, and those would typically be CHAR, VARCHAR etc. LOBs would not work as the JDBC realm implementation issues aResultSet.getString
method call invocation to obtain the password hash.Base64 encoding is not the only supported option. You can perform Hex encoding as well. But you must perform either of these, and configure the JDBC Realm to perform the same at runtime. In the absence of an encoding parameter, Glassfish will convert the byte sequence associated with the digest, to a sequence of characters in the
charset
configured for the realm.I suspect the problem has something to do with the mention of UTF-8 encoding in the expression
input.getBytes("UTF-8")
. It would be worth verifying if the Base64 encoding of the result provided by yourdigest
method actually matches the password hashes stored in the database.Also, considering the reason provided for the failure being
jdbcrealm.invaliduserreason
, I would also suspect that one of the following conditions might be true:base64
orhex
(the case does not matter, going by the source code of the JDBC realm), otherwise you would end up in the scenario where the digest byte array is converted to a character array (which in my opinion is a bit flaky unless you can guarantee that the password provided by users are always in a particular encoding).derby.properties
in the location of your Derby database with the propertyderby.language.logStatementText=true
in it. On shutting down the database, the derby.log file will be populated with all the queries issued by the application server.