SpringSecurity的初始化流程

举报
周杰伦本人 发表于 2022/04/13 13:47:52 2022/04/13
【摘要】 SpringSecurity的初始化流程初始化从SpringSecurity的自动化配置类开始@Configuration(proxyBeanMethods = false)@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)@EnableConfigurationProperties(SecurityProperti...

SpringSecurity的初始化流程

初始化从SpringSecurity的自动化配置类开始

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
@EnableConfigurationProperties(SecurityProperties.class)
@Import({ SpringBootWebSecurityConfiguration.class, WebSecurityEnablerConfiguration.class,
      SecurityDataConfiguration.class })
public class SecurityAutoConfiguration {

   @Bean
   @ConditionalOnMissingBean(AuthenticationEventPublisher.class)
   public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher publisher) {
      return new DefaultAuthenticationEventPublisher(publisher);
   }

}

WebSecurityEnablerConfiguration是重点

@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(WebSecurityConfigurerAdapter.class)
@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@EnableWebSecurity
public class WebSecurityEnablerConfiguration {

}
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,
      SpringWebMvcImportSelector.class,
      OAuth2ImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
   boolean debug() default false;
}

EnableWebSecurity导入了WebSecurityConfiguration,用来配置WebSecurity

EnableGlobalAuthentication注解导入了配置类AuthenticationConfiguration

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import(AuthenticationConfiguration.class)
@Configuration
public @interface EnableGlobalAuthentication {
}

重点分析这两个配置

WebSecurityConfiguration

WebSecurityConfiguration实现了ImportAware 接口,使用@Import注解在@EnableWebSecurity上导入WebSecurityConfiguration之后,在WebSecurityConfiguration的setImportMetadata方法方便获取到@EnableWebSecurity注解中的属性值。

WebSecurityConfiguration实现了BeanClassLoaderAware 方便获取ClassLoader对象

重点看setFilterChainProxySecurityConfigurer方法:主要是用来构建一个WebSecurity对象,并且加载所有的配置类对象。

@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(
      ObjectPostProcessor<Object> objectPostProcessor,
      @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
      throws Exception {
   webSecurity = objectPostProcessor
         .postProcess(new WebSecurity(objectPostProcessor));
   if (debugEnabled != null) {
      webSecurity.debug(debugEnabled);
   }

   webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);

   Integer previousOrder = null;
   Object previousConfig = null;
   for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
      Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
      if (previousOrder != null && previousOrder.equals(order)) {
         throw new IllegalStateException(
               "@Order on WebSecurityConfigurers must be unique. Order of "
                     + order + " was already used on " + previousConfig + ", so it cannot be used on "
                     + config + " too.");
      }
      previousOrder = order;
      previousConfig = config;
   }
   for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
      webSecurity.apply(webSecurityConfigurer);
   }
   this.webSecurityConfigurers = webSecurityConfigurers;
}

手写创建一个WebSecurity,创建出来之后的对象去对象处理后置器中处理,将webSecurity对象注册到Spring容器中。

然后根据每个配置类的@Order注解对webSecurityConfigurations集合中的所有配置类进行排序,因为一个配置类对应一个过滤器链,因为请求到来时需要先和那个过滤器匹配存在优先级问题。

排序后进入for循环,检查是否存在优先级相等问题,如果存在直接抛出异常。最后遍历所有配置类,调用webSecurity.apply方法加到WebSecurity父类中的configs集合中。

有了WebSecurity对象和配置类就可以构建过滤器FilterChainProxy了

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();
}

先判断webSecurityConfigurers集合中是否存在配置类,如果不存在立马创建一个匿名的WebSecurityConfigurerAdapter,否则直接调用

webSecurity.build()进行构建,对所有的配置类WebSecurityConfigurerAdapter实例进行构建,在WebSecurityConfigurerAdapter的init方法中又完成HttpSecurity的构建,HttpSecurity构建过程中完成局部AuthenticationManager对象和每一个具体过滤器的构建。

AuthenticationConfiguration

导入ObjectPostProcessorConfiguration配置类,具体实现类是AutowireBeanFactoryObjectPostProcessor,将一个对象注册到Spring容器中。

@Import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {

构建AuthenticationManager

public AuthenticationManager getAuthenticationManager() throws Exception {
   if (this.authenticationManagerInitialized) {
      return this.authenticationManager;
   }
   AuthenticationManagerBuilder authBuilder = this.applicationContext.getBean(AuthenticationManagerBuilder.class);
   if (this.buildingAuthenticationManager.getAndSet(true)) {
      return new AuthenticationManagerDelegator(authBuilder);
   }

   for (GlobalAuthenticationConfigurerAdapter config : globalAuthConfigurers) {
      authBuilder.apply(config);
   }

   authenticationManager = authBuilder.build();

   if (authenticationManager == null) {
      authenticationManager = getAuthenticationManagerBean();
   }

   this.authenticationManagerInitialized = true;
   return authenticationManager;
}

AuthenticationConfiguration作用:

  1. 导入ObjectPostProcessorConfiguration配置类,具体实现类是AutowireBeanFactoryObjectPostProcessor,将一个对象注册到Spring容器中。
  2. 提供全局的AuthenticationManager

如果重写了AuthenticationManagerBuilder的configure方法,全局AuthenticationManager失效,大部分情况下 我们会重写AuthenticationManagerBuilder的configure方法。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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