【发布时间】:2014-04-16 16:49:37
【问题描述】:
所以我已经将我的 shiro 设置为拥有两个 Realms。使用标准 UsernamePasswordToken 的用户名和密码领域。我还设置了一个自定义承载身份验证令牌,它可以处理从用户传入的令牌。
如果我只使用我的 passwordValidatorRealm 它可以找到,如果没有找到用户抛出未知帐户,如果密码不匹配抛出不正确的凭据,完美。但是,一旦我放入我的 tokenValidatorRealm,它就会抛出一个
org.apache.shiro.authc.AuthenticationException: Authentication token of type [class org.apache.shiro.authc.UsernamePasswordToken] could not be authenticated by any configured realms.
在这种情况下,我的 tokenValidatorRealm 返回 null,因为没有提供任何令牌,因此它会转到 passwordValidatorRealm 并中断。
任何想法为什么引入第二个领域会导致我的工作密码ValidatorRealm 中断?
尝试了不同的身份验证策略,但没有成功。
使用 shiro 1.2.2
编辑
我有两种实现,一种用于密码,一种用于令牌
密码:
public class PasswordAuthorizingRealm extends AuthenticatingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
if (authenticationToken instanceof UsernamePasswordToken) {
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
String username = usernamePasswordToken.getUsername();
char[] password = usernamePasswordToken.getPassword();
if (username == null) {
throw new AccountException("Null usernames are not allowed by this realm!");
}
//Null password is invalid
if (password == null) {
throw new AccountException("Null passwords are not allowed by this realm!");
}
UserService userService = new UserServiceImpl();
User user = userService.getUserByUsername(username);
if (user == null) {
throw new UnknownAccountException("Could not authenticate with given credentials");
}
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, user.getPassword(), "passwordValidatorRealm");
return simpleAuthenticationInfo;
} else {
return null;
}
}
}
和不记名令牌
public class TokenAuthorizingRealm extends AuthorizingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
if (authenticationToken instanceof BearerAuthenticationToken) {
BearerAuthenticationToken bearerAuthenticationToken = (BearerAuthenticationToken) authenticationToken;
String username = "" + bearerAuthenticationToken.getPrincipal();
User user = userService.getUserByUsername(username);
//User with such username has not found
if (user == null) {
throw new UnknownAccountException("Could not authenticate with given credentials");
}
BearerAuthenticationInfo bearerAuthenticationInfo = new BearerAuthenticationInfo(user);
return bearerAuthenticationInfo;
}
}
Shiro 配置
[main]
hashService = org.apache.shiro.crypto.hash.DefaultHashService
hashService.hashIterations = 500000
hashService.hashAlgorithmName = SHA-256
hashService.generatePublicSalt = true
hashService.privateSalt = ****
passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordService.hashService = $hashService
passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
passwordMatcher.passwordService = $passwordService
authc = my.BearerTokenAuthenticatingFilter
tokenValidatorRealm = my.TokenAuthorizingRealm
passwordValidatorRealm = my.PasswordAuthorizingRealm
passwordValidatorRealm.credentialsMatcher = $passwordMatcher
securityManager.realms = $tokenValidatorRealm,$passwordValidatorRealm
这些已经被剥离了一点,删除了日志记录和其他不必要的代码
BearerTokenAuthenticatingFilter,基本上只是检查是否在标头中提供了令牌
private void loginUser(ServletRequest request, ServletResponse response) throws Exception {
BearerAuthenticationToken token = (BearerAuthenticationToken) createToken(request, response);
if (token == null) {
String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken "
+ "must be created in order to execute a login attempt.";
throw new IllegalStateException(msg);
}
try {
Subject subject = getSubject(request, response);
subject.login(token);
onLoginSuccess(token, subject, request, response);
} catch (AuthenticationException e) {
HttpServletResponse httpResponse = WebUtils.toHttp(response);
httpResponse.sendRedirect("login");
}
}
BearerAuthenticationInfo 类
public class BearerAuthenticationInfo implements AuthenticationInfo {
private final PrincipalCollection principalCollection;
private final User user;
public BearerAuthenticationInfo(User user) {
this.user = user;
this.principalCollection = buildPrincipalCollection(user);
}
public PrincipalCollection getPrincipals() {
return principalCollection;
}
public Object getCredentials() {
return user.getUsername();
}
private PrincipalCollection buildPrincipalCollection(User user) {
Collection<String> principals = new ArrayList<String>();
principals.add(user.getUsername());
return new SimplePrincipalCollection(principals, "tokenValidatorRealm");
}
}
【问题讨论】:
-
您能否与我们分享您的领域 doGetAuthenticationInfo 实现以及您如何调用登录?
-
已更新原始帖子并提供更多信息
标签: java authentication shiro