@[TOC]
聊聊SpringSecurity的过滤器链的形成
SpringSecurity的过滤器链是怎么形成的呢?我们一起研究一下。
入口
springboot在启动的时候会加载META-INF/spring.factories下的配置,配置文件中定义了
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration也就是说会自动装配SecurityFilterAutoConfiguration这个类,类上有注解:@AutoConfigureAfter(SecurityAutoConfiguration.class)
意思是在加载SecurityAutoConfiguration类之后再加载SecurityFilterAutoConfiguration类,那么我们看一下SecurityAutoConfiguration类
SecurityAutoConfiguration类中导入了SpringBootWebSecurityConfiguration.class, SpringBootWebSecurityConfiguration上有个注解@EnableWebSecurity,表示开启security安全功能,
注解中又导入了WebSecurityConfiguration.class,WebSecurityConfiguration类的功能就是用来生成过滤器链的
WebSecurityConfiguration的springSecurityFilterChain()方法:
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) public Filter springSecurityFilterChain() throws Exception { boolean hasConfigurers = webSecurityConfigurers != null && !webSecurityConfigurers.isEmpty(); if (!hasConfigurers) { WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor .postProcess(new WebSecurityConfigurerAdapter() { }); webSecurity.apply(adapter); } return webSecurity.build(); }这个方法显然就是构建过滤器链的
深入webSecurity.build()方法会调用AbstractConfiguredSecurityBuilder的doBuild()方法:
@Override protected final O doBuild() throws Exception { synchronized (this.configurers) { this.buildState = BuildState.INITIALIZING; beforeInit(); init(); this.buildState = BuildState.CONFIGURING; beforeConfigure(); configure(); this.buildState = BuildState.BUILDING; O result = performBuild(); this.buildState = BuildState.BUILT; return result; } }doBuild()方法中调用init()方法,这个方法里会获取到SecurityConfigurer的子类,然后遍历所有的子类调用init()方法
init()方法
在WebSecurityConfigurerAdapter的init()方法中:
@Override public void init(WebSecurity web) throws Exception { HttpSecurity http = getHttp(); web.addSecurityFilterChainBuilder(http).postBuildAction(() -> { FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class); web.securityInterceptor(securityInterceptor); }); }configure()方法
init()方法完成后继续执行AbstractConfiguredSecurityBuilder的doBuild()方法中的configure()方法,
这个方法中会调用具体的SecurityConfigurer实例的configure()方法,而SecurityConfigurer实例的configure()中就会把涉及的过滤器添加到HttpSecurity中
performBuild()方法
接下来就会执行AbstractConfiguredSecurityBuilder的performBuild()方法,方法中调用this.filters.sort(this.comparator)来对所有的过滤器进行排序,最终形成的过滤器链:
WebAsyncManagerIntegrationFilter:集成SecurityContext到Spring异步执行机制中的WebAsyncManager 中
SecurityContextPersistenceFilter:请求之前使用从SecurityContextRepository}获得的信息填充到SecurityContextHolder中,并在请求完成并清除上下文持有者后将其存储回存储库中。默认情况下,它使用 HttpSessionSecurityContextRepository。
HeaderWriterFilter:将header信息添加到当前响应中
CsrfFilter:对于post请求添加csrf的token信息,防止csrf gongji
LogoutFilter:匹配logout请求,用户退出后清除认证信息
ValidateCodeFilter:检验码过滤器 自定义的
UsernamePasswordAuthenticationFilter:用户名密码认证过滤器
RequestCacheAwareFilter:缓存HttpServletRequest
SecurityContextHolderAwareRequestFilter:对ServletRequest进行包装
AnonymousAuthenticationFilter:检测SecurityContextHolder中是否没有Authentication对象,如果为空创建匿名用户存入SecurityContextHolder中
SessionManagementFilter:限制一个用户开启多个会话的数量
ExceptionTranslationFilter:异常转换过滤器
FilterSecurityInterceptor:通过过滤器实现对 HTTP 资源进行安全处理
然后创建过滤器链的代理对象FilterChainProxy,返回结果
总结
这篇文章主要讲了过滤器链的创建过程,入口就是SecurityFilterAutoConfiguration类自动装配,总共有14个过滤器,主要是是通过SecurityConfigurer的实例的configure()方法添加到HttpSecurity对象中的