返回

聊聊SpringSecurity的过滤器链的形成

发布时间:2022-09-21 21:54:11 174
# spring# springboot# java# 研究# 信息

聊聊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);
    });
  }
  1. getHttp()方法中添加第一个过滤器链WebAsyncManagerIntegrationFilter类并添加一系列的配置类
  2. 再调用web.addSecurityFilterChainBuilder()方法将HttpSecurity实例添加到WebSecurity的securityFilterChainBuilders属性中

configure()方法

init()方法完成后继续执行AbstractConfiguredSecurityBuilder的doBuild()方法中的configure()方法,

这个方法中会调用具体的SecurityConfigurer实例的configure()方法,而SecurityConfigurer实例的configure()中就会把涉及的过滤器添加到HttpSecurity中

performBuild()方法

接下来就会执行AbstractConfiguredSecurityBuilder的performBuild()方法,方法中调用this.filters.sort(this.comparator)来对所有的过滤器进行排序,最终形成的过滤器链:

WebAsyncManagerIntegrationFilter:集成SecurityContextSpring异步执行机制中的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对象中的

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
Spring @Repository 注解 2022-09-21 21:11:09