• SpringSecurity - 启动流程分析(四)



    活动地址:CSDN21天学习挑战赛

    前言

    SpringSecurity - 启动流程分析(三) 这篇文章的最后,我们知道了 SpringSecurity 最后会在 ApplicationFilterConfig 中加入一个名为 springSecurityFilterChainFilter

    在这里插入图片描述

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

    在这里插入图片描述

    同时我们也可以看到 FilterChains 中只有一个 DefaultSecurityFilterChain,这里贴一下源码:

    // security 的 Filter 排序规则
    private FilterComparator comparator = new FilterComparator();
    
    @Override
    protected DefaultSecurityFilterChain performBuild() {
    	// 排序
    	filters.sort(comparator);
    	return new DefaultSecurityFilterChain(requestMatcher, filters);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    看一下 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());
    	}
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    这里定义了 SpringSecurity 提供的默认过滤器的执行顺序。

    分析

    下面我们就按照上面给出的执行顺序看一下这些默认的 Filters,由于这里的 Filter 比较多,所以这里就只是简单介绍一下每一个 Filter 的作用,重要的 Filter 后面再通过几篇文章重点说,比如 UsernamePasswordAuthenticationFilter

    1、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 {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    从源码注释中可以看出,该 Filter 的作用提供了 SecurityContextSpring WebWebAsyncManager 的集成,处理在异步线程中的 SecurityContext

    2、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 {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Filter 的主要作用是为了加载 SecurityContextSecurityContextHolder 中,从命名中就可以看出来(Spring 的命名很是严谨,一般都可以见名知意)。

    3、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 {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Filter 的作用主要是对响应信息的请求头添加一些配置

    4、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 {}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Filter 的作用主要是防止跨站请求伪造

    5、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 {}

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Filter 的作用主要是对登出操作做处理,我们可以自定义 LogoutHandles 来处理登出逻辑,并且可以配置 LogoutSuccessHandle 或者指定 logoutSuccessUrl

    6、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 {}

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Filter 的作用是处理默认的 /login 请求,也是 SpringSecurity 提供的默认用户密码登录认证,后面会详细分析该 Filter

    7、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 {}

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    Filter 的作用是用于用户登录成功后,重新恢复跳转到登录之前的请求

    8、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 {}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Filter 的作用是拓展了 HttpServletRequest,在每一个请求中添加了一些额外的方法,比如:getPrincipal() 方法。可以在任何地方获取 SecurityContext

    9、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 {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Filter 的作用是对匿名用户做一些处理,比如:设置 principalauthorities

    10、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 {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Filter 的作用是管理 Session

    11、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 {}

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Filter 的作用是对于任意的 AccessDeniedException 类型的异常和 AuthenticationException 类型异常的处理

    12、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 {}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Filter 的作用主要是做认证和授权拦截,比如我们配置了对某个 url 限制某种角色能够访问,就是在这里进行鉴权,判断是否放行

    总结

    以上就是基于 SpringSecurity 5.3.9.RELEASE 对默认 Filters 的简单分析,目前还不具备详细分析每一个 Filter 实现过程的能力,还有一些概念需要了解,后面会在 SpringSecurity 学习 专栏中对一些重要的 Filter 展开讨论

  • 相关阅读:
    十进制转换成2进制
    软件测试期末考试成分
    计算机网络第五章——传输层(上)
    .NET开源且免费的Windows远程桌面管理软件
    H.264 帧内预测
    报表开发工具 Stimulsoft Reports V2022.3.5系列发布!
    SpringBoot自定义参数校验注解
    深度学习相关VO梳理
    可调用对象、std..function、std..bind
    【漏洞复现】大华智慧园区综合管理平台信息泄露漏洞
  • 原文地址:https://blog.csdn.net/qiaohao0206/article/details/126336352