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);
}
}
}
}