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
的实现变量。