我正在使用Apache Shiro和自定义JDBC领域来检索用户的salt,密码,哈希算法名称和数据库中的哈希迭代次数,这些都是作为单独的列存储的。
问题是我不确定在使用PasswordMatcher验证用户密码是否与数据库中存储的密码匹配时,我应该如何处理从数据库中检索到的盐。
使用HashedCredentialsMatcher时,使用setCredentialsSalt
方法设置salt,但是使用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(Object submittedPlaintext,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使用盐?
答案 0 :(得分:1)
我在Shiro邮件列表上发布了一条消息并得到一个回复,说默认情况下PasswordMatcher不会查看AuthenticationInfo中除authenticationInfo.getCredentials()之外的任何内容。
上找到邮件列表中的已存档邮件答案 1 :(得分:0)
我花了一段时间在我的一个项目中追捕这个网址 - http://meri-stuff.blogspot.com/2011/04/apache-shiro-part-2-realms-database-and.html
该文章链接到此文件JNDIAndSaltAwareJdbcRealm
我在我的项目中成功使用了该类,在密码哈希中使用了salt。
HTH
答案 2 :(得分:0)
如果您将Shiro Command Line Hasher创建的凭据存储在Shiro1CryptFormat中,那么您可以在您的领域中使用DefaultPasswordService
:
final PasswordMatcher passwordMatcher = new PasswordMatcher();
passwordMatcher.setPasswordService(new DefaultPasswordService());
realm.setCredentialsMatcher(passwordMatcher);