定义接口获取用户用户名密码 AuthenticationToken,在
子类实现:
Authenticator接口用来认证用户,可以看出参数就是AutenticationToken,从中获取用户名密码进行验证
AuthenticationInfo和AuthenticationToken比较相似,AuthenticationInfo是已经验证过的保存的用户信息,而AuthenticationToken是第三方通过login发送过来等待验证的用户信息。SaltedAuthenticationInfo定义了获取盐的方法,MergableAuthenticationInfo定义了把一个AuthenticationInfo和现有的AuthenticationInfo合并的方法。
LogoutAware当用户退出的时候的回调接口
AbstractAuthenticator抽象类,实现了接口方法authentication(AuthentiationToken),调用了模板方法doAuthentication(AuthenticationToken)来验证用户,如果成功调用notifySuccess循环调用集合listeners中的监听器,调用监听器的onSuccess方法,如果失败掉用notifyFailure方法,调用监听器的onFailure方法,同时抛出认证异常。实现了接口方法onLogout,在此方法中调用了notifyLogout遍历集合listeners中的监听器,调用监听器的onLogout方法。
用户认证监听器接口:
ModularRealmAuthenticator是接口Authenticator的默认实现类,主要有以下功能:
1:实现父类模板方法:doAuthenticator(AuthenticationToken) ,根据realm数量调用doSingleRealmAuthentication或者doMultiRealmAuthentication方法
2:重写父类onLogout,调用父类onLogout,然后遍历调用realm集合中的realm的onLogout方法
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
//验证realm集合存在
assertRealmsConfigured();
Collection<Realm> realms = getRealms();
if (realms.size() == 1) {
return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
} else {
return doMultiRealmAuthentication(realms, authenticationToken);
}
}
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);
}
//最终调用的realm的getAuthenticationInfo获取AuthenticationInfo
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;
}
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;
}
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);
}
}
}
}