文章目录
前言
本文是接上一章Spring Security源码分析一:Spring Security认证过程进一步分析Spring Security用户名密码登录授权是如何实现得;
类图
源码分析
如图所示,显示了登录认证过程中的 filters
相关的调用流程,作者将几个自认为重要的 filters 标注了出来
从图中可以看出执行的顺序。来看看几个作者认为比较重要的Filter
的处理逻辑,UsernamePasswordAuthenticationFilter
,AnonymousAuthenticationFilter
,ExceptionTranslationFilter
,FilterSecurityInterceptor
以及相关的处理流程如下所述;
UsernamePasswordAuthenticationFilter
整个调用流程是,先调用其父类 AbstractAuthenticationProcessingFilter.doFilter()
方法,然后再执行 UsernamePasswordAuthenticationFilter.attemptAuthentication()
方法进行验证;
AbstractAuthenticationProcessingFilter
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
#1.判断当前的filter是否可以处理当前请求,不可以的话则交给下一个filter处理
if (!requiresAuthentication(request, response)) {
chain.doFilter(request, response);
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Request is to process authentication");
}
Authentication authResult;
try {
#2.抽象方法由子类UsernamePasswordAuthenticationFilter实现
authResult = attemptAuthentication(request, response);
if (authResult == null) {
// return immediately as subclass has indicated that it hasn't completed
// authentication
return;
}
#2.认证成功后,处理一些与session相关的方法
sessionStrategy.onAuthentication(authResult, request, response);
}
catch (InternalAuthenticationServiceException failed) {
logger.error(
"An internal error occurred while trying to authenticate the user.",
failed);
#3.认证失败后的的一些操作
unsuccessfulAuthentication(request, response, failed);
return;
}
catch (AuthenticationException failed) {
// Authentication failed
unsuccessfulAuthentication(request, response, failed);
return;
}
// Authentication success
if (continueChainBeforeSuccessfulAuthentication) {
chain.doFilter(request, response);
}
#3. 认证成功后的相关回调方法 主要将当前的认证放到SecurityContextHolder中
successfulAuthentication(request, response, chain, authResult);
}
整个程序的执行流程如下:
- 判断
filter
是否可以处理当前的请求,如果不可以则放行交给下一个filter
- 调用抽象方法
attemptAuthentication
进行验证,该方法由子类UsernamePasswordAuthenticationFilter
实现 - 认证成功以后,回调一些与
session
相关的方法; - 认证成功以后,认证成功后的相关回调方法;认证成功以后,认证成功后的相关回调方法;
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Authentication success. Updating SecurityContextHolder to contain: "
+ authResult);
}
SecurityContextHolder.getContext().setAuthentication(authResult);
rememberMeServices.loginSuccess(request, response, authResult);
// Fire event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
authResult, this.getClass()));
}
successHandler.onAuthenticationSuccess