likesyour 2016-11-04
ModularRealmAuthenticator类主要是用来实现项目中出现多realm的情况下,根据认证策略来对各个realm进行认证,它继承了AbstractAuthenticator抽象类,先对其解析如下:
1.AbstractAuthenticator抽象类
可以参照AbstractAuthenticator抽象类源码解析,主要实现了认证并且在认证成功或者失败后通知认证监听器组。
2.ModularRealmAuthenticator类
2.1.属性数据
private Collection<Realm> realms;//多个安全数据源
private AuthenticationStrategy authenticationStrategy;//认证策略
2.2.构造方法(默认的认证策略是至少一个成功的策略)
public ModularRealmAuthenticator() {
        this.authenticationStrategy = new AtLeastOneSuccessfulStrategy();
}
2.3.设置realm集合
public void setRealms(Collection<Realm> realms) {
        this.realms = realms;
}
2.4.获取realm集合
protected Collection<Realm> getRealms() {
        return this.realms;
}
2.5.获取认证策略
public AuthenticationStrategy getAuthenticationStrategy() {
        return authenticationStrategy;
}
2.7.设置认证策略
public void setAuthenticationStrategy(AuthenticationStrategy authenticationStrategy) {
        this.authenticationStrategy = authenticationStrategy;
}
2.8.验证realms集合不为空(如果为空,则抛出异常)
protected void assertRealmsConfigured() throws IllegalStateException {
        Collection<Realm> realms = getRealms();
        if (CollectionUtils.isEmpty(realms)) {
            String msg = "Configuration error:  No realms have been configured!  One or more realms must be " +
                    "present to execute an authentication attempt.";
            throw new IllegalStateException(msg);
        }
    }
2.9.单一realm的认证
protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) {
        if (!realm.supports(token)) {
            String msg = "Realm [" + realm + "] does not support authentication token [" +
                    token + "].  Please ensure that the appropriate Realm implementation is " +
                    "configured correctly or that the realm accepts AuthenticationTokens of this type.";
            throw new UnsupportedTokenException(msg);
        }
        AuthenticationInfo info = realm.getAuthenticationInfo(token);
        if (info == null) {
            String msg = "Realm [" + realm + "] was unable to find account data for the " +
                    "submitted AuthenticationToken [" + token + "].";
            throw new UnknownAccountException(msg);
        }
        return info;
    }
2.10.多realm认证
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());
        }
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;
                Throwable t = null;
                try {
                    info = realm.getAuthenticationInfo(token);
                } catch (Throwable throwable) {
                    t = throwable;
                    if (log.isDebugEnabled()) {
                        String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:";
                        log.debug(msg, t);
                    }
                }
aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);
            } else {
                log.debug("Realm [{}] does not support token {}.  Skipping realm.", realm, token);
            }
        }
aggregate = strategy.afterAllAttempts(token, aggregate);
        return aggregate;
    }
2.11.认证操作(判断realm的个数,如果realm为一个,则进行单realm认证;如果realm为多个,则进行多realm认证,实现了AbstractAuthenticator的方法)
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);
        }
    }
2.12.登出(覆盖了AbstractAuthenticator的方法)
public void onLogout(PrincipalCollection principals) {
        super.onLogout(principals);
        Collection<Realm> realms = getRealms();
        if (!CollectionUtils.isEmpty(realms)) {
            for (Realm realm : realms) {
                if (realm instanceof LogoutAware) {
                    ((LogoutAware) realm).onLogout(principals);
                }
            }
        }
    }