shiro多realm整合的spring-boot案例剖析
概述:shiro认证的流程主要是通过securityManager调用login(Subject subject, AuthenticationToken token)方法,实际上委托的是Authenticator(认证器进行认证),默认情况下使用的是
ModularRealmAuthenticator认证器,如果我们只有1个realm,最终的认证操作就是调用这个realm,如果我们有多个realm呢?这个时候就需要我们对ModularRealmAuthenticator认证器进行扩展。
一、下面是subject.login()执行的代码调用片段
public void login(AuthenticationToken token) throws AuthenticationException {
clearRunAsIdentitiesInternal();
Subject subject = securityManager.login(this, token);
上面是DelegatingSubject的login方法
public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo info;
try {
info = authenticate(token);
} catch (AuthenticationException ae) {
}
}
上面是DefaultSecurityManager的login方法
public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {
return this.authenticator.authenticate(token);
}
实际调用的是AuthenticatingSecurityManager的authenticate方法, 这个this.authenticator就是ModularRealmAuthenticator。
二、ModularRealmAuthenticator默认的多reaml是按什么策略进行处理的呢?
1、authenticate方法的公共处理,实际上调用的是doAuthenticate(token)方法。
public final AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {
AuthenticationInfo info;
try {
info = doAuthenticate(token); // 实际主要的认证方法
if (info == null) { // 没有返回info就抛出auth异常
throw new AuthenticationException(msg);
}
} catch (Throwable t) {
AuthenticationException ae = null;
if (t instanceof AuthenticationException) {
ae = (AuthenticationException) t;
}
if (ae == null) {
ae = new AuthenticationException(msg, t);
} // 任何认证过程异常包装成auth异常进行抛出
throw ae;
}
return info;
}
2、我们看看doAuthenticate的默认实现,根据配置了realms的个数来判断是调用单个还是doMultiRealmAuthentication()方法
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
assertRealmsConfigured();
Collection<Realm> realms = getRealms();
if (realms.size() == 1) {
return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
} else {
return doMultiRealmAuthentication(realms, authenticationToken);
}
}
3、在说doMultiRealmAuthentication方法前,我们可以在ModularRealmAuthenticator类里找到new的AuthenticationStrategy策略。这个策略决定了doMultiRealmAuthentication的实现方式。我们先看看AbstractAuthenticationStrategy的默认实现。
public abstract class AbstractAuthenticationStrategy implements AuthenticationStrategy {
// 全部realm认证前--创建一个空info
public AuthenticationInfo beforeAllAttempts(Collection<? extends Realm> realms, AuthenticationToken token) throws AuthenticationException {
return new SimpleAuthenticationInfo();
}
// 单个realm认证前--直接返回
public AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo aggregate) throws AuthenticationException {
return aggregate;
}
// 单个realm认证前--将上一个和此次的info进行合并
public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo, AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
AuthenticationInfo info;
if (singleRealmInfo == null) {