WebSecurityConfiguration的重点是通过WebSecurity创建FilterChainProxy

  • • 先分析内部的方法

1、elegatingApplicationListener

  • • 看名字就能看出来注册了一个委托类型的监听器
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware { 
   ......
   @Bean
   public static DelegatingApplicationListener delegatingApplicationListener() {
      return new DelegatingApplicationListener();
   }
   ......
}
  • • 内部其实就是一个很简单的把监听器又嵌套了一层,在内部for循环发送事件,所以说重点就是如何注册内部的监听器的
public final class DelegatingApplicationListener implements
      ApplicationListener<ApplicationEvent> {
   private List<SmartApplicationListener> listeners = new CopyOnWriteArrayList<>();

   public void onApplicationEvent(ApplicationEvent event) {
      if (event == null) {
         return;
      }
      for (SmartApplicationListener listener : listeners) {
         Object source = event.getSource();
         if (source != null && listener.supportsEventType(event.getClass())
               && listener.supportsSourceType(source.getClass())) {
            listener.onApplicationEvent(event);
         }
      }
   }

   /**
    * Adds a new SmartApplicationListener to use.
    *
    * @param smartApplicationListener the SmartApplicationListener to use. Cannot be
    * null.
    */
   public void addListener(SmartApplicationListener smartApplicationListener) {
      Assert.notNull(smartApplicationListener,
            "smartApplicationListener cannot be null");
      listeners.add(smartApplicationListener);
   }
}
  • • Debug就会发现默认只有SessionManagementConfigurer会注册一个SessionRegistryImpl
  • • SessionRegistryImpl是针对SpringSecurity内部维护的SessionInformation的操作 比如说用户登录后,才会创建会话session,那么通常会有一个SpringSecurity的SessionInformation的创建

2、setFilterChainProxySecurityConfigurer

  • • 重点就是创建了WebSecurity,并注册对应的配置类
  • • 是创建FilterChainProxy的核心类
@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
      @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
      throws Exception {
   this.webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
   if (this.debugEnabled != null) {
      this.webSecurity.debug(this.debugEnabled);
   }
   //先对配置类进行排序
   webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);
   Integer previousOrder = null;
   Object previousConfig = null;
   //这个for循环的意思是:配置类可以通过@Order进行排序,但是如果@Order中的value值相同就表示无法进行排序,就直接抛出异常
   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) {
      this.webSecurity.apply(webSecurityConfigurer);
   }
   this.webSecurityConfigurers = webSecurityConfigurers;
}
  • • 入参有两个重要的类

2.1 ObjectPostProcessor

  • • ObjectPostProcessor
  • • SecurityConfigurer
  • • 首先这个类有一个重要的实现AutowireBeanFactoryObjectPostProcessor,默认注册到容器的也是这个类
  • • Spring Security会通过new创建很多bean, 为了让这些由SpringSecurity创建的bean也和跟spring容器中的bean有同样的生命周期,所以出现了此类
final class AutowireBeanFactoryObjectPostProcessor
     implements ObjectPostProcessor<Object>, DisposableBean, SmartInitializingSingleton {

  private final Log logger = LogFactory.getLog(getClass());

  private final AutowireCapableBeanFactory autowireBeanFactory;

  private final List<DisposableBean> disposableBeans = new ArrayList<>();

  private final List<SmartInitializingSingleton> smartSingletons = new ArrayList<>();

  AutowireBeanFactoryObjectPostProcessor(AutowireCapableBeanFactory autowireBeanFactory) {
     Assert.notNull(autowireBeanFactory, "autowireBeanFactory cannot be null");
     this.autowireBeanFactory = autowireBeanFactory;
  }

   /**
  * 让这些由SpringSecurity创建的bean也和跟spring容器中的bean有同样的生命周期,也能注入相应的依赖,从而进入准备好被使用的状态
  * @param object the object to initialize
  * @param <T>
  * @return
  @Override
  @SuppressWarnings("unchecked")
  public <T> T postProcess(T object) {
     if (object == null) {
        return null;
     }
     T result = null;
     try {
        //进行初始化
        result = (T) this.autowireBeanFactory.initializeBean(object, object.toString());
     }
     catch (RuntimeException ex) {
        Class<?> type = object.getClass();
        throw new RuntimeException("Could not postProcess " + object + " of type " + type, ex);
     }
     //进行自动装配属性
     this.autowireBeanFactory.autowireBean(object);
     if (result instanceof DisposableBean) {
        this.disposableBeans.add((DisposableBean) result);
     }
     if (result instanceof SmartInitializingSingleton) {
        this.smartSingletons.add((SmartInitializingSingleton) result);
     }
     return result;
  }

  @Override
  public void afterSingletonsInstantiated() {
     for (SmartInitializingSingleton singleton : this.smartSingletons) {
        singleton.afterSingletonsInstantiated();
     }
  }

  @Override
  public void destroy() {
     for (DisposableBean disposable : this.disposableBeans) {
        try {
           disposable.destroy();
        }
        catch (Exception ex) {
           this.logger.error(ex);
        }
     }
  }

}

2.2 SecurityConfigurer

  • • SpringSecurity在创建对应的过滤器的时候是通过建造者模式进行创建的,SecurityConfigurer算是比较顶级的一个类了,较为完整的构建流程如下:
public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
      extends AbstractSecurityBuilder<O> {
    ......
    @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;
       }
  ......
  • • 完整的走完了beforeInit、init、beforeConfigure、configure、performBuild,也映射出了建造者模式下的构建状态
private enum BuildState {

   /**
    * 表明当前构建器还未进行构建
    */
   UNBUILT(0),

   /**
    * 表明当前构建器正在执行初始化方法,具体规则在doBuild()方法中,下同
    */
   INITIALIZING(1),

   /**
    * 表明当前构建器执行完初始化方法
    */
   CONFIGURING(2),

   /**
    * 表明当前构建器已经执行完配置方法
    */
   BUILDING(3),

   /**
    * 表明当前构建器已经执行完构建方法
    */
   BUILT(4);
}

3、autowiredWebSecurityConfigurersIgnoreParents

  • • 作用是获取容器中的WebSecurityConfigurer
  • • WebSecurityConfigurer的实现类WebSecurityConfigurerAdapter是配置Spring Security过滤器的实现类
public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
      extends AbstractSecurityBuilder<O> {
    ......
    @Bean
    public static AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
          ConfigurableListableBeanFactory beanFactory) {
       return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
    }
  ......

4、setImportMetadata

  • • 本质上就是获取在@EnableWebSecurity中设置的是否开启debug日志打印
public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
      extends AbstractSecurityBuilder<O> {
    ......
    @Override
    public void setImportMetadata(AnnotationMetadata importMetadata) {
       //默认只有WebSecurityEnablerConfiguration导入了此类,而此类一定标志了@EnableWebSecurity
       Map<String, Object> enableWebSecurityAttrMap = importMetadata
             .getAnnotationAttributes(EnableWebSecurity.class.getName());
       AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes.fromMap(enableWebSecurityAttrMap);
       this.debugEnabled = enableWebSecurityAttrs.getBoolean("debug");
       if (this.webSecurity != null) {
          this.webSecurity.debug(this.debugEnabled);
       }
    }
  ......

5、springSecurityFilterChain

  • • 往容器中注册过滤器,是构建过滤器的入口,也就是注册FilterChainProxy
public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
      extends AbstractSecurityBuilder<O> {
    ......
@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();
}
  ......
  • • 第六行代码会判断是否有配置类的存在,即使我们没有注册WebSecurityConfigurer的配置类,也依旧会有一个DefaultConfigurerAdapter注册到容器中
graph TD
SecurityAutoConfiguration --> SpringBootWebSecurityConfiguration --> DefaultConfigurerAdapter