我一直在以明文形式存储我的密码以用于开发目的,但是想要开始存储哈希值,但是到目前为止还没有成功使GlassFish针对散列密码进行正确的身份验证,因为以下SecurityException:
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 Security - jdbcRealm: How to configure login with SHA-256 digest建议您确实需要这样做。
所以我想我想知道的是,GlassFish是否期望一个String(VARCHAR)或一个byte [](BLOB)作为数据库中的密码字段,我是否正确地记录了密码,并且它是正确的另外Base64编码密码哈希?
谢谢!
答案 0 :(得分:2)
GlassFish是否期望String(VARCHAR)或byte [](BLOB)作为数据库中的密码字段?
它期望一个列映射到JDBC中的Java类型java.lang.String
,并且那些列通常是CHAR,VARCHAR等.LOB不起作用,因为JDBC领域实现发出ResultSet.getString
方法调用调用获取密码哈希。
我是否正确地对密码进行了哈希处理,并且另外Base64对密码哈希进行编码是否正确?
Base64编码不是唯一受支持的选项。您也可以执行十六进制编码。但是您必须执行其中任何一个,并配置JDBC Realm以在运行时执行相同的操作。如果没有编码参数,Glassfish会将与摘要关联的字节序列转换为为域配置的charset
中的字符序列。
我怀疑问题与表达式input.getBytes("UTF-8")
中提到的UTF-8编码有关。值得验证您的digest
方法提供的结果的Base64编码是否与存储在数据库中的密码哈希实际匹配。
另外,考虑到失败原因为jdbcrealm.invaliduserreason
,我还怀疑下列情况之一可能属实:
base64
或hex
中的一个(这种情况无关紧要,按照JDBC领域的源代码),否则你最终会在摘要字节数组被转换的情况下到一个字符数组(在我看来有点片状,除非你能保证用户提供的密码总是采用特定的编码)。derby.properties
的文件放在Derby数据库的位置,其中包含属性derby.language.logStatementText=true
。关闭数据库时,将使用应用程序服务器发出的所有查询填充derby.log文件。