AbstractAuthenticationProcessingFilter 是處理 form 登陸的過濾器,與 form 登陸有關的所有操作都是在該類及其子類中進行的。
繼承關系
public abstract class AbstractAuthenticationProcessingFilter extends GenericFilterBean
implements ApplicationEventPublisherAware, MessageSourceAware {
AbstractAuthenticationProcessingFilter 繼承自 GenericFilterBean,而 GenericFilterBean 是 spring 框架中的過濾器類,實現(xiàn)了接口 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/>的實現(xiàn)類。 -
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;
可見該方法是個等待子類實現(xiàn)的虛擬方法,對于用戶帳號密碼的校驗在該方法中進行。
-
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 的實現(xiàn)變量。
附
