聊聊SpringSecurity的过滤器链的形成

举报
周杰伦本人 发表于 2022/09/29 13:23:01 2022/09/29
【摘要】 聊聊SpringSecurity的过滤器链的形成SpringSecurity的过滤器链是怎么形成的呢?我们一起研究一下。 入口springboot在启动的时候会加载META-INF/spring.factories下的配置,配置文件中定义了org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springfra...

聊聊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攻击

LogoutFilter:匹配logout请求,用户退出后清除认证信息

ValidateCodeFilter:检验码过滤器 自定义的

UsernamePasswordAuthenticationFilter:用户名密码认证过滤器

RequestCacheAwareFilter:缓存HttpServletRequest

SecurityContextHolderAwareRequestFilter:对ServletRequest进行包装

AnonymousAuthenticationFilter:检测SecurityContextHolder中是否没有Authentication对象,如果为空创建匿名用户存入SecurityContextHolder中

SessionManagementFilter:限制一个用户开启多个会话的数量

ExceptionTranslationFilter:异常转换过滤器

FilterSecurityInterceptor:通过过滤器实现对 HTTP 资源进行安全处理

然后创建过滤器链的代理对象FilterChainProxy,返回结果

总结

这篇文章主要讲了过滤器链的创建过程,入口就是SecurityFilterAutoConfiguration类自动装配,总共有14个过滤器,主要是是通过SecurityConfigurer的实例的configure()方法添加到HttpSecurity对象中的

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。