阅读完需:约 3 分钟
AbstractAuthenticationProcessingFilter 是处理 form 登陆的过滤器,与 form 登陆有关的所有操作都是在该类及其子类中进行的。
继承关系
public abstract class AbstractAuthenticationProcessingFilter extends GenericFilterBean
implements ApplicationEventPublisherAware, MessageSourceAware {
AbstractAuthenticationProcessingFilter 继承自 GenericFilterBean,而 GenericFilterBean 是 spring 框架中的过滤器类,实现了接口 javax.servlet.Filter。
成员变量
AbstractAuthenticationProcessingFilter 中的成员变量主要有以下
public abstract class AbstractAuthenticationProcessingFilter extends GenericFilterBean
implements ApplicationEventPublisherAware, MessageSourceAware {
// ~ Static fields/initializers
// =====================================================================================
// ~ Instance fields
// ================================================================================================
protected ApplicationEventPublisher eventPublisher;
protected AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new WebAuthenticationDetailsSource();
private AuthenticationManager authenticationManager;
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private RememberMeServices rememberMeServices = new NullRememberMeServices();
private RequestMatcher requiresAuthenticationRequestMatcher;
private boolean continueChainBeforeSuccessfulAuthentication = false;
private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy();
private boolean allowSessionCreation = true;
private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
其中有几个比较重要的成员变量:
-
authenticationManager即为我们在 spring 配置文件中注册的<authentication-manager/>的实现类。 -
AuthenticationSuccessHandler为授权成功处理类。 -
AuthenticationFailureHandler为授权失败处理类。
流程分析
因为 AbstractAuthenticationProcessingFilter 为本质上是一个 servlet 过滤器,因此找到其入口函数 doFilter()。
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (!requiresAuthentication(request, response)) {
chain.doFilter(request, response);
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Request is to process authentication");
}
Authentication authResult;
try {
--> 1 authResult = attemptAuthentication(request, response);
if (authResult == null) {
// return immediately as subclass has indicated that it hasn't completed
// authentication
return;
}
sessionStrategy.onAuthentication(authResult, request, response);
}
catch (InternalAuthenticationServiceException failed) {
logger.error(
"An internal error occurred while trying to authenticate the user.",
failed);
--> 2 unsuccessfulAuthentication(request, response, failed);
return;
}
catch (AuthenticationException failed) {
// Authentication failed
--> 3 unsuccessfulAuthentication(request, response, failed);
return;
}
// Authentication success
if (continueChainBeforeSuccessfulAuthentication) {
chain.doFilter(request, response);
}
--> 4 successfulAuthentication(request, response, chain, authResult);
}
其中:
-
try代码快中的--> 1处代码表示该处会调用attemptAuthentication()方法进行身份校验处理。attemptAuthentication()方法本体如下所示:
public abstract Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException, IOException,
ServletException;
可见该方法是个等待子类实现的虚拟方法,对于用户帐号密码的校验在该方法中进行。
-
catch代码块中的--> 2和--> 3处代码表示身份校验失败之后调用方法unsuccessfulAuthentication(),该方法本体如下所示:
protected void unsuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, AuthenticationException failed)
throws IOException, ServletException {
SecurityContextHolder.clearContext();
if (logger.isDebugEnabled()) {
logger.debug("Authentication request failed: " + failed.toString(), failed);
logger.debug("Updated SecurityContextHolder to contain null Authentication");
logger.debug("Delegating to authentication failure handler " + failureHandler);
}
rememberMeServices.loginFail(request, response);
failureHandler.onAuthenticationFailure(request, response, failed);
}
该方法中最重要的一条语句是failureHandler.onAuthenticationFailure(request, response, failed);,表明验证身份信息失败之后调用类 failureHandler 的 onAuthenticationFailure() 方法。而 failureHandler 是 AuthenticationFailureHandler 的实例变量。
-
--> 4处代码表示验证身份信息成功后,调用successfulAuthentication()方法,其方法本体如下:
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(request, response, authResult);
}
其中,最重要的一行代码是 successHandler.onAuthenticationSuccess(request, response, authResult);,表示身份验证成功后调用 successHandler 的 onAuthenticationSuccess 方法。而 successHandler 为 AuthenticationSuccessHandler 的实现变量。

