2

出于开发目的,我一直以纯文本形式存储我的密码,但想开始存储哈希值,但由于以下 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 Security - jdbcRealm: How to configure login with SHA-256 digest建议您确实需要这样做。

所以我想我想知道的是,GlassFish 是否需要一个字符串(VARCHAR)或一个字节 [](BLOB)作为数据库中的密码字段,我是否正确地散列密码,另外 Base64 编码是否正确密码哈希?

谢谢!

4

1 回答 1

2

GlassFish 是否需要一个字符串 (VARCHAR) 或一个字节 [] (BLOB) 作为数据库中的密码字段?

它需要一个映射到 JDBC 中的 Java 类型的列,这些通常是 CHAR、VARCHAR 等。由于 JDBC 领域实现发出方法调用以获取密码哈希java.lang.String,因此 LOB 将不起作用。ResultSet.getString

我是否正确地对密码进行哈希处理,另外对密码哈希进行 Base64 编码是否正确?

Base64 编码不是唯一受支持的选项。您也可以执行十六进制编码。但是您必须执行其中任何一个,并将 JDBC 领域配置为在运行时执行相同的操作。在没有编码参数的情况下,Glassfish 会将与摘要关联的字节序列转换charset为为领域配置的字符序列。

我怀疑这个问题与表达式中提到 UTF-8 编码有关input.getBytes("UTF-8")digest如果您的方法提供的结果的 Base64 编码实际上与存储在数据库中的密码哈希匹配,则值得验证。

另外,考虑到失败的原因是jdbcrealm.invaliduserreason,我还怀疑以下情况之一可能是真的:

  • 没有为 JDBC Realm 指定 encoding 参数;它最好是base64or之一hex(大小写无关紧要,通过 JDBC 领域的源代码),否则您最终会遇到将摘要字节数组转换为字符数组的场景(在我看来是有点不稳定,除非您可以保证用户提供的密码始终采用特定的编码)。
  • 数据库中不存在用户的密码哈希。请参阅我之前执行的 SQL 查询的答案;您可能想自己运行查询。您可以记录由 Derby 发出的语句(如果您将其用作数据库),方法是在您的 Derby 数据库的位置放置一个名为的文件derby.properties,其中包含该属性derby.language.logStatementText=true。在关闭数据库时,derby.log 文件将填充应用程序服务器发出的所有查询。
  • Glassfish准备的SQL语句不正确。
  • 无法建立与数据库的连接。
于 2011-07-28T19:57:10.603 回答