AuthenticationManager----认证接口,该对象提供了认证入口,接收一个Authentication对象作为参数;
Authentication对象本身也是一个接口,提供了获取认证用户的用户名、密码、用户详情、认证状态等方法。
分析Authentication对象时我们主要关注常用的下面两个类RememberMeAuthenticationToken,UsernamePasswordAuthenticationToken
ProviderManager----AuthenticationManager接口的实现类,实现了基本的认证逻辑并扩展了一些功能,其中ProviderManager实现类的构造函数中使用List<AuthenticationProvider> providers作为入参,意义在于为认证引入更多不同形式的认证实现,通过AuthenticationProvider可以扩展认证方式。
//ProviderManager中的认证实现源码
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
Class<? extends Authentication> toTest = authentication.getClass();
AuthenticationException lastException = null;
AuthenticationException parentException = null;
Authentication result = null;
Authentication parentResult = null;
boolean debug = logger.isDebugEnabled();
//此处就用到了引入的认证实现,认证过程会先使用引入AuthenticationProvider的认证,如果引入的认证都没有认证成功则会使用原始的AuthenticationManager提供的认证
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
}
if (debug) {
logger.debug("Authentication attempt using "
+ provider.getClass().getName());
}
try {
result = provider.authenticate(authentication);
if (result != null) {
copyDetails(authentication, result);
break;
}
}
catch (AccountStatusException e) {
prepareException(e, authentication);
//如果身份验证失败是由于无效的帐户状态引起的,请避免轮询其他提供认证的程序
throw e;
}
catch (InternalAuthenticationServiceException e) {
prepareException(e, authentication);
throw e;
}
catch (AuthenticationException e) {
lastException = e;
}
}
if (result == null && parent != null) {
// Allow the parent to try.
try {
//引入的AuthenticationProvider都认证失败则使用原始的AuthenticationManager提供的认证
result = parentResult = parent.authenticate(authentication);
}
catch (ProviderNotFoundException e) {
// ignore as we will throw below if no other exception occurred prior to
// calling parent and the parent
// may throw ProviderNotFound even though a provider in the child already
// handled the request
}
catch (AuthenticationException e) {
lastException = parentException = e;
}
}
if (result != null) {
if (eraseCredentialsAfterAuthentication
&& (result instanceof CredentialsContainer)) {
// 认证完成。从身份验证中删除凭据和其他秘密数据
((CredentialsContainer) result).eraseCredentials();
}
// 如果父 AuthenticationManager 已尝试并成功,那么它将发布一个 AuthenticationSuccessEvent 如果父 AuthenticationManager 已经发布了它,此检查可防止重复的 AuthenticationSuccessEvent
if (parentResult == null) {
eventPublisher.publishAuthenticationSuccess(result);
}
return result;
}
if (lastException == null) {
lastException = new ProviderNotFoundException(messages.getMessage(
"ProviderManager.providerNotFound",
new Object[] { toTest.getName() },
"No AuthenticationProvider found for {0}"));
}
// 如果父 AuthenticationManager 已尝试但失败,则它将发布 AbstractAuthenticationFailureEvent 如果父 AuthenticationManager 已发布,此检查可防止重复 AbstractAuthenticationFailureEvent
if (parentException == null) {
prepareException(lastException, authentication);
}
throw lastException;
}
AuthenticationProvider----ProviderManager 通过 AuthenticationProvider 扩展出更多的验证提供的方式;而 AuthenticationProvider 本身也就是一个接口,从类图中我们可以看出它的实现类AbstractUserDetailsAuthenticationProvider和AbstractUserDetailsAuthenticationProvider的子类DaoAuthenticationProvider。DaoAuthenticationProvider是Spring Security中一个核心的Provider,对所有的数据库提供了基本方法和入口。