前言
本文是接上一章Spring Security源码分析一:Spring Security认证过程进一步分析Spring Security
用户名密码登录授权是如何实现得;
类图
调试过程
使用debug方式启动https://github.com/longfeizheng/logback该项目,浏览器输入http://localhost:8080/persons,用户名随意,密码123456即可;
源码分析
如图所示,显示了登录认证过程中的 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);
}
整个程序的执行流程如下:
1. 判断filter是否可以处理当前的请求,如果不可以则放行交给下一个filter
2. 调用抽象方法attemptAuthentication
进行验证,该方法由子类UsernamePasswordAuthenticationFilter
实现
3. 认证成功以后,回调一些与 session 相关的方法;
4. 认证成功以后,认证成功后的相关回调方法;认证成功以后,认证成功后的相关回调方法;
protected