Shiro - 无法使用散列密码进行身份验证

Posted

技术标签:

【中文标题】Shiro - 无法使用散列密码进行身份验证【英文标题】:Shiro - Cannot authenticate using hashed passwords 【发布时间】:2014-12-29 14:56:22 【问题描述】:

我正在尝试使用 Shiro 对我正在构建的 JSF Web 应用程序进行身份验证和授权。不幸的是,我仍然难以理解它们是如何组合在一起的。

我已经成功(100% 使用 shiro.ini 文件)将身份验证配置回用于存储测试凭据集的 JDBC 领域。当凭据以明文形式存储时,它对我来说非常有效。

我的最终目标是统一 mysql 数据库中的现有凭据集。密码存储为 SHA-256 加盐哈希。我花了一整天的时间阅读可用的文档(减去 Javadocs),但我仍然难以理解如何设置它。

为了尝试分阶段实施,我将 shiro.ini 修改如下,目的是简单地使用 SHA-256 哈希:

[main]
dataSource = org.apache.shiro.jndi.JndiObjectFactory
dataSource.resourceName = jdbc/Communicator_dev
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource = $dataSource
dataSource.resourceRef = true;

jdbcRealm.authenticationQuery = select password from account where site_id = ?
jdbcRealm.userRolesQuery = select user_role from web_roles where site_id = ?

# From https://***.com/questions/20742666/shiro-with-jdbc-and-hashed-passwords.
#
passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
#configure the passwordService to use the settings you desire
#...
passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
passwordMatcher.passwordService = $passwordService
#...
# Finally, set the matcher on a realm that requires password matching for account authentication:
jdbcRealm.credentialsMatcher = $passwordMatcher

实际的登录逻辑是在页面支持 bean 中编程的。这是我目前正在使用的简单测试源:

    // Create auth token
    UsernamePasswordToken token = new UsernamePasswordToken(this.siteID, this.password);
    // Get the current subject
    Subject currentUser = SecurityUtils.getSubject();
    // Attempt to login
    try 
        currentUser.login(token);
     catch (AuthenticationException e) 
        System.out.println("Invalid creds.");
        return "";
    
    return "authenticated.xhtml?faces-redirect=true";

这段代码与存储在我的 RDBMS 中的纯文本密码完美配合,但现在我已经对它们进行了哈希处理,它失败了。

根据我对框架的理解,我认为问题出在 AuthenticationToken 上。我知道我需要使用不同的令牌来最终实现存储在我的 RDBMS 中的盐渍哈希,但我对如何继续感到困惑。

(1) 我不想重新发明***。 Shiro 是否有一些本机可以做到这一点的东西?我已经查看了 Les 到 PasswordMatcher 和 PasswordService 的链接(来自链接 shiro with jdbc and hashed passwords),但这仍然不清楚。我需要对PasswordMatcher 进行子类化吗?

(2) 一个架构问题:谁真正调用了 doCredentialsMatch(..) 方法?在 login(...) 方法执行期间是 Realm 吗?

(3) doCredentialsMap(...) 方法的 AuthenticationInfo 参数.. 是由 Realm 提供的吗?由于 Realms 封装了实际的安全数据,在我的例子中,这是一个从 RDBMS 返回密码的 SQL 查询创建的对象吗?

非常感谢您的宝贵时间!当我全神贯注时,我希望能够为文档做出贡献。

【问题讨论】:

【参考方案1】:

第 1 项: 我怀疑您可能遇到this issue 涉及默认为“NO_SALT”的 JdbcRealm 的“salt style”参数。这会导致哈希工作,但如果您在密码中添加盐,领域将无法正确匹配它们。

以下是您之后的步骤:

基于 COLUMN 的 salt 样式的默认查询如下所示,“select password, password_salt from users where username = ?”。如果您不能使用该结构,您需要通过您的“shiro.ini”提供一个具有类似结构的新查询。

jdbcRealm.authenticationQuery=select password, salt_column_here from users where username = ?

这是related question。

第 2 项:是的,领域调用 doCredentialsMatch(..) 方法。

第 3 项:是的,领域将 AuthenticationInfo 提供给 doCredentialsMatch(..) 方法。

【讨论】:

仍然很困惑,虽然你的盐风格链接肯定有帮助。一旦 salt 样式设置为“COLUMN”,如何指定实际包含 salt 值的列? 嗨 Naitouk,我不知道你问了一个后续问题。如果您查看示例查询,则 select 子句有两列,“password”和“salt_column_here”。第二列是映射您的数据库盐列以便 Shiro 可以找到它。

以上是关于Shiro - 无法使用散列密码进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 shiro 1.2.1 对数据库进行身份验证

带有休眠和散列密码的 Spring Security DB 身份验证?

Shiro安全框架学习01 -入门

shiro 简单的身份验证 案例

Shiro 学习笔记——shiro身份验证

Shiro-身份验证