请确保至少一个领域可以验证这些令牌 [英] Please ensure that at least one realm can authenticate these tokens
问题描述
因此,我将shiro设置为具有两个领域.使用标准UsernamePasswordToken的用户名和密码领域.我还设置了一个自定义承载身份验证令牌,该令牌可以处理从用户传入的令牌.
So I have set up my shiro to have two Realms. A Username and Password Realm, using the standard UsernamePasswordToken. I have also set up a Custom Bearer Authentication Token that works off a token passed in from the user.
如果我只使用我的passwordValidatorRealm,它可以正常工作;如果找不到用户,则抛出未知帐户;如果密码不匹配,则抛出错误的凭据,这很完美.但是,一旦我将我的tokenValidatorRealm放进去,它就会抛出一个
If i just use my passwordValidatorRealm it works find, if no user is found throws unknown account, if password doesn’t match throws incorrect credentials, perfect. But as soon as i put in my tokenValidatorRealm it throws a
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并中断了.
In this instance my tokenValidatorRealm returns null as no token was provided, so it moves on to the passwordValidatorRealm and just breaks.
有什么想法为什么引入第二个Realm会导致我的工作passwordValidatorRealm中断?
Any ideas why introducing a second Realm will cause my working passwordValidatorRealm to break?
尝试了不同的身份验证策略,但是没有运气.
Have tried with different authentication strategies, and no luck there.
使用shiro 1.2.2
Using shiro 1.2.2
编辑
我有两种实现方式,一种用于密码,一种用于令牌
I have two implementations, one for password and one for token
密码:
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
这些内容已被删除,删除了日志记录和其他不必要的代码
These have been stripped out a bit, removed logging and other unnecessary code
BeererTokenAuthenticatingFilter,基本上只是检查标头中是否提供了令牌
The BearerTokenAuthenticatingFilter, just basically checks if a token has been supplied in the header if has
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类
BearerAuthenticationInfo class
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");
}
}
推荐答案
看起来像是预期的行为.
Looks like it is expected behavior.
如果您查看ModularRealmAuthenticator的Javadoc:
If you look at the javadoc for ModularRealmAuthenticator:
* @throws AuthenticationException if the user could not be authenticated or the user is denied authentication
* for the given principal and credentials.
*/
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
如果您对该异常有疑问,则可能需要更改调用身份验证的代码才能预期此异常.
If you are having problems with the exception, you might need to change the code that calls the authentication to expect this exception.
其他搜索的左侧:
您的TokenAuthorizingRealm类中可能缺少支持方法.
You might have a missing supports method in your TokenAuthorizingRealm class.
类似
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof BearerAuthenticationToken;
}
应该在场.
这篇关于请确保至少一个领域可以验证这些令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!