活动地址:CSDN21天学习挑战赛
在 SpringSecurity - 启动流程分析(三) 这篇文章的最后,我们知道了 SpringSecurity 最后会在 ApplicationFilterConfig 中加入一个名为 springSecurityFilterChain 的 Filter:

其中包含了 SpringSecurity 默认提供的 12 个过滤器:

同时我们也可以看到 FilterChains 中只有一个 DefaultSecurityFilterChain,这里贴一下源码:
// security 的 Filter 排序规则
private FilterComparator comparator = new FilterComparator();
@Override
protected DefaultSecurityFilterChain performBuild() {
// 排序
filters.sort(comparator);
return new DefaultSecurityFilterChain(requestMatcher, filters);
}
看一下 FilterComparator 的源码:
final class FilterComparator implements Comparator<Filter>, Serializable {
// 初始顺序值为100
private static final int INITIAL_ORDER = 100;
// 步长为100
private static final int ORDER_STEP = 100;
private final Map<String, Integer> filterToOrder = new HashMap<>();
FilterComparator() {
Step order = new Step(INITIAL_ORDER, ORDER_STEP);
put(ChannelProcessingFilter.class, order.next());
put(ConcurrentSessionFilter.class, order.next());
put(WebAsyncManagerIntegrationFilter.class, order.next());
put(SecurityContextPersistenceFilter.class, order.next());
put(HeaderWriterFilter.class, order.next());
put(CorsFilter.class, order.next());
put(CsrfFilter.class, order.next());
put(LogoutFilter.class, order.next());
filterToOrder.put(
"org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter",
order.next());
filterToOrder.put(
"org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationRequestFilter",
order.next());
put(X509AuthenticationFilter.class, order.next());
put(AbstractPreAuthenticatedProcessingFilter.class, order.next());
filterToOrder.put("org.springframework.security.cas.web.CasAuthenticationFilter",
order.next());
filterToOrder.put(
"org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter",
order.next());
filterToOrder.put(
"org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter",
order.next());
put(UsernamePasswordAuthenticationFilter.class, order.next());
put(ConcurrentSessionFilter.class, order.next());
filterToOrder.put(
"org.springframework.security.openid.OpenIDAuthenticationFilter", order.next());
put(DefaultLoginPageGeneratingFilter.class, order.next());
put(DefaultLogoutPageGeneratingFilter.class, order.next());
put(ConcurrentSessionFilter.class, order.next());
put(DigestAuthenticationFilter.class, order.next());
filterToOrder.put(
"org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter", order.next());
put(BasicAuthenticationFilter.class, order.next());
put(RequestCacheAwareFilter.class, order.next());
put(SecurityContextHolderAwareRequestFilter.class, order.next());
put(JaasApiIntegrationFilter.class, order.next());
put(RememberMeAuthenticationFilter.class, order.next());
put(AnonymousAuthenticationFilter.class, order.next());
filterToOrder.put(
"org.springframework.security.oauth2.client.web.OAuth2AuthorizationCodeGrantFilter",
order.next());
put(SessionManagementFilter.class, order.next());
put(ExceptionTranslationFilter.class, order.next());
put(FilterSecurityInterceptor.class, order.next());
put(SwitchUserFilter.class, order.next());
}
...
}
这里定义了 SpringSecurity 提供的默认过滤器的执行顺序。
下面我们就按照上面给出的执行顺序看一下这些默认的 Filters,由于这里的 Filter 比较多,所以这里就只是简单介绍一下每一个 Filter 的作用,重要的 Filter 后面再通过几篇文章重点说,比如 UsernamePasswordAuthenticationFilter:
WebAsyncManagerIntegrationFilter/**
* Provides integration between the {@link SecurityContext} and Spring Web's
* {@link WebAsyncManager} by using the
* {@link SecurityContextCallableProcessingInterceptor#beforeConcurrentHandling(org.springframework.web.context.request.NativeWebRequest, Callable)}
* to populate the {@link SecurityContext} on the {@link Callable}.
*/
public final class WebAsyncManagerIntegrationFilter extends OncePerRequestFilter {}
从源码注释中可以看出,该 Filter 的作用提供了 SecurityContext 与 Spring Web 的 WebAsyncManager 的集成,处理在异步线程中的 SecurityContext。
SecurityContextPersistenceFilter/**
* Populates the {@link SecurityContextHolder} with information obtained from the
* configured {@link SecurityContextRepository} prior to the request and stores it back in
* the repository once the request has completed and clearing the context holder. By
* default it uses an {@link HttpSessionSecurityContextRepository}. See this class for
* information HttpSession related configuration options.
*/
public class SecurityContextPersistenceFilter extends GenericFilterBean {}
该 Filter 的主要作用是为了加载 SecurityContext 到 SecurityContextHolder 中,从命名中就可以看出来(Spring 的命名很是严谨,一般都可以见名知意)。
HeaderWriterFilter/**
* Filter implementation to add headers to the current response. Can be useful to add
* certain headers which enable browser protection. Like X-Frame-Options, X-XSS-Protection
* and X-Content-Type-Options.
*/
public class HeaderWriterFilter extends OncePerRequestFilter {}
该 Filter 的作用主要是对响应信息的请求头添加一些配置
CsrfFilter/**
*
* Applies
* CSRF
* protection using a synchronizer token pattern. Developers are required to ensure that
* {@link CsrfFilter} is invoked for any request that allows state to change. Typically
* this just means that they should ensure their web application follows proper REST
* semantics (i.e. do not change state with the HTTP methods GET, HEAD, TRACE, OPTIONS).
*
*/
public final class CsrfFilter extends OncePerRequestFilter {}
该 Filter 的作用主要是防止跨站请求伪造
LogoutFilter/**
* Logs a principal out.
*
* Polls a series of {@link LogoutHandler}s. The handlers should be specified in the order
* they are required. Generally you will want to call logout handlers
* TokenBasedRememberMeServices and SecurityContextLogoutHandler
* (in that order).
*
* After logout, a redirect will be performed to the URL determined by either the
* configured LogoutSuccessHandler or the logoutSuccessUrl, depending on
* which constructor was used.
*/
public class LogoutFilter extends GenericFilterBean {}
该 Filter 的作用主要是对登出操作做处理,我们可以自定义 LogoutHandles 来处理登出逻辑,并且可以配置 LogoutSuccessHandle 或者指定 logoutSuccessUrl
UsernamePasswordAuthenticationFilter/**
* Processes an authentication form submission. Called
* {@code AuthenticationProcessingFilter} prior to Spring Security 3.0.
*
* Login forms must present two parameters to this filter: a username and password. The
* default parameter names to use are contained in the static fields
* {@link #SPRING_SECURITY_FORM_USERNAME_KEY} and
* {@link #SPRING_SECURITY_FORM_PASSWORD_KEY}. The parameter names can also be changed by
* setting the {@code usernameParameter} and {@code passwordParameter} properties.
*
* This filter by default responds to the URL {@code /login}.
*/
public class UsernamePasswordAuthenticationFilter extends
AbstractAuthenticationProcessingFilter {}
该 Filter 的作用是处理默认的 /login 请求,也是 SpringSecurity 提供的默认用户密码登录认证,后面会详细分析该 Filter
RequestCacheAwareFilter/**
* Responsible for reconstituting the saved request if one is cached and it matches the
* current request.
*
* It will call
* {@link RequestCache#getMatchingRequest(HttpServletRequest, HttpServletResponse)
* getMatchingRequest} on the configured RequestCache. If the method returns a
* value (a wrapper of the saved request), it will pass this to the filter chain's
* doFilter method. If null is returned by the cache, the original request is
* used and the filter has no effect.
*/
public class RequestCacheAwareFilter extends GenericFilterBean {}
该 Filter 的作用是用于用户登录成功后,重新恢复跳转到登录之前的请求
SecurityContextHolderAwareRequestFilter/**
* A Filter which populates the ServletRequest with a request
* wrapper which implements the servlet API security methods.
*
* {@link SecurityContextHolderAwareRequestWrapper} is extended to provide the following
* additional methods:
*
*/
public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {}
该 Filter 的作用是拓展了 HttpServletRequest,在每一个请求中添加了一些额外的方法,比如:getPrincipal() 方法。可以在任何地方获取 SecurityContext。
AnonymousAuthenticationFilter/**
* Detects if there is no {@code Authentication} object in the
* {@code SecurityContextHolder}, and populates it with one if needed.
*/
public class AnonymousAuthenticationFilter extends GenericFilterBean implements
InitializingBean {}
该 Filter 的作用是对匿名用户做一些处理,比如:设置 principal 和 authorities
SessionManagementFilter/**
* Detects that a user has been authenticated since the start of the request and, if they
* have, calls the configured {@link SessionAuthenticationStrategy} to perform any
* session-related activity such as activating session-fixation protection mechanisms or
* checking for multiple concurrent logins.
*/
public class SessionManagementFilter extends GenericFilterBean {}
该 Filter 的作用是管理 Session
ExceptionTranslationFilter/**
* Handles any AccessDeniedException and AuthenticationException
* thrown within the filter chain.
*
* This filter is necessary because it provides the bridge between Java exceptions and
* HTTP responses. It is solely concerned with maintaining the user interface. This filter
* does not do any actual security enforcement.
*/
public class ExceptionTranslationFilter extends GenericFilterBean {}
该 Filter 的作用是对于任意的 AccessDeniedException 类型的异常和 AuthenticationException 类型异常的处理
FilterSecurityInterceptor/**
* Performs security handling of HTTP resources via a filter implementation.
*
* The SecurityMetadataSource required by this security interceptor is of
* type {@link FilterInvocationSecurityMetadataSource}.
*
* Refer to {@link AbstractSecurityInterceptor} for details on the workflow.
*
*/
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements
Filter {}
该 Filter 的作用主要是做认证和授权拦截,比如我们配置了对某个 url 限制某种角色能够访问,就是在这里进行鉴权,判断是否放行
以上就是基于 SpringSecurity 5.3.9.RELEASE 对默认 Filters 的简单分析,目前还不具备详细分析每一个 Filter 实现过程的能力,还有一些概念需要了解,后面会在 SpringSecurity 学习 专栏中对一些重要的 Filter 展开讨论