请确保至少有一个领域可以对这些令牌进行身份validation

所以我已经设置了我的shiro有两个领域。 用户名和密码域,使用标准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破坏?

尝试过不同的身份validation策略,但没有运气。

使用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; } } } 

和Bearer Token

 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 principals = new ArrayList(); principals.add(user.getUsername()); return new SimplePrincipalCollection(principals, "tokenValidatorRealm"); } } 

看起来是预期的行为。

如果你看看ModularRealmAuthenticator的javadoc:

  * @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 { 

如果您遇到exception问题,则可能需要更改调用身份validation的代码以期望此exception。


留给其他搜索:

您的TokenAuthorizingRealm类中可能缺少支持方法。

就像是

 @Override public boolean supports(AuthenticationToken token) { return token instanceof BearerAuthenticationToken; } 

应该在场。

这个讨论帮我解决了类似的问题。 我想通过应用程序本身对用户进行身份validation,而不是使用任何Shiro默认实现。 为此,我们必须inheritanceAuthenticatingRealm,重写doGetAuthenticationInfo并将此域声明为validation域。

 public class PasswordAuthorizingRealm extends AuthenticatingRealm { @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { 

在Shiro.ini:

 passwordValidatorRealm = my.PasswordAuthorizingRealm