【发布时间】:2014-10-02 15:05:05
【问题描述】:
我必须在 Shiro 中创建一个自定义领域,并且我必须使用带有“salt”的密码
我使用的代码是这样的:
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
...
Admin admin = query.getByUsername(username);
String passwordSalted = admin.getPassword();
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, passwordSalted, new SimpleByteSource(MY_PRIVATE_SALT), getName());
return info;
}
public Admin createAdmin(AuthenticationToken authenticationToken){
DefaultHashService hashService = new DefaultHashService();
hashService.setHashIterations(500000);
hashService.setHashAlgorithmName(Sha256Hash.ALGORITHM_NAME);
hashService.setPrivateSalt(new SimpleByteSource(MY_PRIVATE_SALT)); // Same salt as in shiro.ini, but NOT base64-encoded.
hashService.setGeneratePublicSalt(true);
DefaultPasswordService passwordService = new DefaultPasswordService();
passwordService.setHashService(hashService);
String encryptedPassword = passwordService.encryptPassword(authenticationToken.getCredentials());
Admin admin = new Admin();
String principal = authenticationToken.getPrincipal().toString();
admin.setUsername(principal);
admin.setPassword(encryptedPassword);
return admin;
}
我使用函数“createAdmin”创建一个Admin,然后我把它存入数据库,像这样:
UsernamePasswordToken u = new UsernamePasswordToken("foo","qwerty") ;
Admin admin = createAdmin(u);
query.save(admin);
保存的密码是这样的:
$shiro1$SHA-256$50000$M7T93MZ65TCxXBsD7JFa9A==$gJcEf2oSKE/RKXifwYiJCaHU7X10ng1PxqL3AEMvmjE=
不知道为什么验证失败:
Factory<SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
AuthenticationToken authenticationToken = new UsernamePasswordToken("foo", "qwerty");
Subject usr = SecurityUtils.getSubject();
try {
securityManager.login(usr, authenticationToken);
} catch (Exception e) {
log.error("error");
}
还有我的 shiro.ini:
[main]
customSecurityRealm=cl.fooproyect.CustomRealm
已解决:
为了解决这个问题,我必须更改 shiro.ini 和 createAdmin。我让 shiro 负责创造盐。 这个解决方案对我有用。
shiro.ini 的变化
[main]
passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
passwordMatcher.passwordService = $passwordService
customSecurityRealm=cl.doman.punto.vaadin.shiro.CustomRealm
customSecurityRealm.credentialsMatcher = $passwordMatcher
securityManager.realms = $customSecurityRealm
createAdmin 的变化:
public Admin createAdmin(AuthenticationToken authenticationToken){
DefaultHashService hashService = new DefaultHashService();
DefaultPasswordService passwordService = new DefaultPasswordService();
String encryptedPassword = passwordService.encryptPassword(authenticationToken.getCredentials());
Admin admin = new Admin();
String principal = authenticationToken.getPrincipal().toString();
admin.setUsername(principal);
admin.setPassword(encryptedPassword);
return admin;
}
【问题讨论】:
-
您的代码看起来不错。如果您使用 shiro 源代码调试登录方法,通常速度足够快,但实际上无法通过身份验证。
-
“提交的令牌 [org.apache.shiro.authc.UsernamePasswordToken ... 的凭据与预期的凭据不匹配。” :S,凭证失败。
-
AuthenticationToken 了解密码“$shiro1$sha...”的当前格式吗?我有很多问题,我找不到程序员创建加盐密码然后使用它的示例
-
我很久没有使用 shiro,但我看到你使用自定义哈希服务来编码密码,而不是用于身份验证。我的建议:确认它与标准哈希服务一起使用,然后搜索文档以查看在哪里以及如何使用
login中的自定义哈希服务 -
我们使用的配置与您大致相同,但我们使用的是 spring,它工作正常。我看不到您如何配置 securityManager,您确定它使用与您创建用户时相同的哈希/盐设置吗?