将 Shiro 的 PasswordMatcher 与自定义领域一起使用
Posted
技术标签:
【中文标题】将 Shiro 的 PasswordMatcher 与自定义领域一起使用【英文标题】:Using Shiro's PasswordMatcher with a custom realm 【发布时间】:2012-09-17 09:02:57 【问题描述】:我正在使用带有自定义 JDBC 领域的 Apache Shiro 从数据库中检索用户的盐、密码、哈希算法名称和哈希迭代次数,这些都存储为单独的列。
问题是我不确定在使用 PasswordMatcher 验证用户密码是否与存储在数据库中的密码匹配时,我应该如何处理从数据库中检索到的 salt。
当使用 HashedCredentialsMatcher 时,盐分是使用 setCredentialsSalt
方法设置的,但是在使用 PasswordMatcher 而不是 HashedCredentialsMatcher 时,情况似乎并非如此。
我在自定义 JDBC 领域中使用的代码如下
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
//code to retrieve user details from database removed for brevity
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, passwdSalt.password, getName());
info.setCredentialsSalt(new SimpleByteSource(passwdSalt.salt));
DefaultPasswordService passwordService = new DefaultPasswordService();
DefaultHashService hashService = new DefaultHashService();
PasswordMatcher passwordMatcher = new PasswordMatcher();
hashService.setHashAlgorithmName(passwdSalt.hashAlgorithmName);
hashService.setHashIterations(passwdSalt.hashIterations);
passwordService.setHashService(hashService);
passwordMatcher.setPasswordService(passwordService);
setCredentialsMatcher(passwordMatcher);
return info;
单步执行代码后,我确认问题肯定是由于在对用户输入的密码进行哈希处理时未使用盐,以便将其与数据库中的哈希密码进行匹配。在 DefaultPasswordService.java 中,当在第 160 行调用方法 passwordsMatch(ObjectmittedPlaintext, String saved) 时,名为 request
的对象包含以下内容
algorithmName=null
iterations=0
salt=null
source=cGFzc3dvcmQ=
161行的下一行代码调用computeHash(request)
在 DefaultHashService.java 中,当调用 computeHash(HashRequest request)
方法时,在第 155 行和第 157 行,变量 algorithmName 和 iterations 分别正确设置为 SHA-256
和 1
。在第 159 行,方法 getPublicSalt(request)
被调用,但是它返回 null。
有没有其他人使用 Shiro 的 PasswordMatcher 和自定义领域?如果你如何告诉 Shiro 使用盐?
【问题讨论】:
【参考方案1】:如果您将Shiro Command Line Hasher 创建的凭据存储在Shiro1CryptFormat 中,那么您可以在您的领域中使用DefaultPasswordService
:
final PasswordMatcher passwordMatcher = new PasswordMatcher();
passwordMatcher.setPasswordService(new DefaultPasswordService());
realm.setCredentialsMatcher(passwordMatcher);
【讨论】:
【参考方案2】:我在 Shiro 邮件列表上发布了一条消息,并得到回复说 PasswordMatcher 默认不查看 AuthenticationInfo 中的任何内容,而不是 authenticationInfo.getCredentials()。
如需了解更多详情,请访问邮件列表中的存档邮件http://shiro-user.582556.n2.nabble.com/Migrating-from-HashedCredentialMatcher-to-PasswordMatcher-td7577808.html
【讨论】:
【参考方案3】:我花了一些时间在我的一个项目中寻找这个网址 - http://meri-stuff.blogspot.com/2011/04/apache-shiro-part-2-realms-database-and.html
文章链接到这个文件JNDIAndSaltAwareJdbcRealm
我已在我的项目中成功使用该类在密码哈希中使用盐。
HTH
【讨论】:
感谢您的快速回复。 Meri 关于使用 Shiro 的出色页面是我正在使用的自定义领域的原始基础,并且在使用 HashedCredentialsMatcher 时效果很好,但如果我将其换成 PasswordMatcher,盐似乎会丢失。 @PaulH - 对不起,我应该仔细阅读这个问题。看看我在我的项目中做了什么。我们必须在设置中使用存储过程来生成具有给定盐的密码哈希。 别担心,当您从数据库中检索记录时,您是如何处理盐分的,以便将散列密码与用户输入的密码进行比较?您还在代码中使用 HashedCredentialsMatcher 还是 PasswordMatcher? 似乎凌晨 2 点是尝试理解 6 个月前写得不好的代码的最佳时机。我已将文件放在 pastie 中。我会在几个小时后再次登录(睡一觉之后),看看我是否能理解它,如果你无法理解的话。以上是关于将 Shiro 的 PasswordMatcher 与自定义领域一起使用的主要内容,如果未能解决你的问题,请参考以下文章
将 Shiro 1.2.6 更新到 1.3.0 会中断对服务器端的访问
如果你的shiro没学明白,那么应该看看这篇文章,将shiro整合进springboot