shiro多realm抛出异常问题
关于这个问题百度会搜到很多内容,但是大多数都不全,只是提到了一部分内容,所以综合本人以及网上搜到的内容,提出如下解决方案:
我是使用了两个Realm,一个用于用户登录验证和访问权限获取;一个用于jwt token的认证,所以出现了
Authentication token of type [class org.apache.shiro.authc.Username
PasswordToken] could not be authenticated by any configured realms.
其中涉及到的原理方面的东西我就不多说了,网上讲的比我清楚,我这里直接贴出全部的解决代码:
1.在每个realm中都要有support方法的重写:
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof UsernamePasswordToken;
}
2.自定义一个类继承ModularRealmAuthenticator,并重写doMultiRealmAuthentication方法:
private static final Logger log = LoggerFactory.getLogger(MyModularRealmAuthenticator.class);
@Override
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
AuthenticationStrategy strategy = getAuthenticationStrategy();
AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);
if (log.isTraceEnabled()) {
log.trace("Iterating through {} realms for PAM authentication", realms.size());
}
AuthenticationException authenticationException = null;
for (Realm realm : realms) {
aggregate = strategy.beforeAttempt(realm, token, aggregate);
if (realm.supports(token)) {
log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);
AuthenticationInfo info = null;
try {
info = realm.getAuthenticationInfo(token);
} catch (AuthenticationException e) {
authenticationException = e;
if (log.isDebugEnabled()) {
String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:";
log.debug(msg, e);
}
}
aggregate = strategy.afterAttempt(realm, token, info, aggregate, authenticationException);
} else {
log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token);
}
}
if(authenticationException != null){
throw authenticationException;
}
aggregate = strategy.afterAllAttempts(token, aggregate);
return aggregate;
}
3.在shiro的配置类中注入自定义类(大多数网上都缺少这部分内容)
@Bean
public Authenticator authenticator() {
ModularRealmAuthenticator authenticator = new MyModularRealmAuthenticator();
authenticator.setRealms(Arrays.asList(shiroRealm(), loginRealm()));
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return authenticator;
}
@Bean("securityManager")
public DefaultSecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置自定义realm
Set<Realm> realms = new HashSet<Realm>();
realms.add(shiroRealm());
realms.add(loginRealm());
securityManager.setRealms(realms);
//关闭shiro自带的session
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator();
sessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator);
securityManager.setSubjectDAO(subjectDAO);
securityManager.setAuthenticator(authenticator());//解决多realm的异常问题重点在此
return securityManager;
}