SpringSecurity的初始化流程

简介: SpringSecurity的初始化流程

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方法。

相关文章
|
4月前
|
Java Spring 容器
深入Spring原理-4.Aware接口、初始化和销毁执行顺序、Scope域
深入Spring原理-4.Aware接口、初始化和销毁执行顺序、Scope域
75 0
|
2月前
|
Java 容器 Spring
SpringBoot:Bean生命周期自定义初始化和销毁
SpringBoot:Bean生命周期自定义初始化和销毁
|
9月前
|
安全 Java 数据库
SpringSecurity-4-认证流程源码解析
SpringSecurity-4-认证流程源码解析
47 0
|
9月前
|
安全
springsecurity配置类以及授权逻辑的编写
springsecurity配置类以及授权逻辑的编写
62 0
|
9月前
|
XML Java 数据库
SpringIOC操作Bean管理--最终章
SpringIOC操作Bean管理--最终章
59 0
|
10月前
|
安全 Java 数据库连接
四.SpringSecurity基础-自定义登录流程
SpringSecurity基础-自定义登录流程
|
8月前
|
安全 Java Spring
SpringSecurity 初始化解析
分析知道了SpringSecurity对一个请求的具体处理流程
30 0
|
11月前
|
Java 数据安全/隐私保护 Spring
spring通过事件进行权限验证
spring通过事件进行权限验证
|
12月前
|
SQL 存储 数据库
Flowable 设置流程变量的四种方式
Flowable 设置流程变量的四种方式
|
Java
SpringBoot项目启动过程中做数据资源初始化的方式
SpringBoot项目启动过程中做数据资源初始化的方式
360 0