1、使用自定义MultiRealmAuthenticator
<bean id="authenticator" class="com.xxx.commons.shiro.MultiRealmAuthenticator">2、MultiRealmAuthenticator类
import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.pam.AuthenticationStrategy; import org.apache.shiro.authc.pam.ModularRealmAuthenticator; import org.apache.shiro.realm.Realm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collection; /** * Created by wanter on 2019/9/25. */ public class MultiRealmAuthenticator extends ModularRealmAuthenticator { private static final Logger log = LoggerFactory.getLogger(ModularRealmAuthenticator.class); @Override protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) throws AuthenticationException { 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; } }原理:与原org.apache.shiro.authc.pam.ModularRealmAuthenticator 类的区别在于添加了对异常的捕获
if(authenticationException != null){ throw authenticationException; }为了防止出现AuthenticationException 异常覆盖的问题,每个realm中加入support方法
@Override public boolean supports(AuthenticationToken var1){ return var1 instanceof UsernamePasswordToken; }