GlassFish SHA-256摘要认证

时间:2011-07-28 18:34:47

标签: java java-ee jdbc glassfish sha256

我一直在以明文形式存储我的密码以用于开发目的,但是想要开始存储哈希值,但是到目前为止还没有成功使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编码密码哈希?

谢谢!

1 个答案:

答案 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,我还怀疑下列情况之一可能属实:

  • 没有为JDBC Realm指定编码参数;它应该最好是base64hex中的一个(这种情况无关紧要,按照JDBC领域的源代码),否则你最终会在摘要字节数组被转换的情况下到一个字符数组(在我看来有点片状,除非你能保证用户提供的密码总是采用特定的编码)。
  • 数据库中的用户不存在密码哈希。请参阅我之前关于the SQL query executed的回答;您可能想要自己运行查询。您可以记录Derby发出的语句(如果您将其用作数据库),方法是将名为derby.properties的文件放在Derby数据库的位置,其中包含属性derby.language.logStatementText=true。关闭数据库时,将使用应用程序服务器发出的所有查询填充derby.log文件。
  • Glassfish编写的SQL语句不正确。
  • 无法建立与数据库的连接。