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 - 无法使用散列密码进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章