前言
本章讨论SpringSecurity中的构建器。
构建器
SecurityBuilder< O>
构建器的顶级接口,下文中所有”构建器”指的就是它或它的子类。只有一个方法:
O build() throws Exception;
ps:泛型O,指的是被构建的对象的类型。
AbstractSecurityBuilder< O>
构建器接口抽象实现。主要做的事情是,保证在多线程的情况下,只构建一次对象。
这里没有使用synchronized,而是使用jdk中高大上的解决线程同步的方法:cas。当然这个不是我们讨论的重点。要记住的是继承了AbstractSecurityBuilder的构建器,在多线程的情况下只会创建一次,具体创建的方法是:
//build()--->doBuild();
protected abstract O doBuild() throws Exception;
ps:泛型O,指的是被构建的对象的类型。
AbstractConfiguredSecurityBuilder< O, B extends SecurityBuilder< O>>
可配置的构建器。PS:O还是指的是被构建的对象类型,而B指的是构建O这个对象的构建器的类型。
它的几个重要的属性:
//构建器的配置器的集合
LinkedHashMap configurers;
//构建器的配置器共享的对象
HashMap sharedObjects;
//后置处理器
ObjectPostProcessor objectPostProcessor
configurers属性的要注意的是,它的add方法叫:apply(configurer);这个在后面还会常用到。
在它的父类中,我们就知道,build委托给doBuild()来做具体的构建工作,而前者主要负责多线程情况下不重复创建。那么这个方法在子类中是怎样实现的呢?如下:
@Override
protected final O doBuild() throws Exception {
synchronized (configurers) {
buildState = BuildState.INITIALIZING;
beforeInit();
init();
buildState = BuildState.CONFIGURING;
beforeConfigure();
configure();
buildState = BuildState.BUILDING;
O result = performBuild();
buildState = BuildState.BUILT;
return result;
}
}
典型“模版方法”设计模式。父类定义步骤及顺序,具体实现由子类完成。当然,这里init()和configure()父类已经给出了实现,无需子类实现:
private void init() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.init((B) this);
}
//ps:老实说,写这篇文章的时候,configurersAddedInInitializing和configurers还不是很清楚...
for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {
configurer.init((B) this);
}
}
private void configure() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.configure((B) this);
}
}
我们在看下它的继承关系:
三个子类,都是非常非常非常重要的构建器。
- AuthenticationManagerBuilder,用来构建授权管理器
- WebSecurity,用来构建“过滤器链的代理”
- HttpSecurity,用来构建“过滤器链”
AuthenticationManagerBuilder
看它的结构:
注意到它实现了ProviderManagerBuilder< AuthenticationManagerBuilder>接口,这个接口是用来构建ProviderManager。ProviderManager是AuthenticationManager的子类。
AuthenticationManagerBuilder的功能是创建AuthenticationManager
WebSecurity
它是为了创建“过滤器链代理”,即:FilterChainProxy对象。
正是FilterChainProxy的创建,触发了HttpSecurity的构建。
FilterChainProxy
一个SecurityFilterChain对象就是一个“过滤器链代理”,它包含了多条过滤器链。当请求来的时候,迭代这些链,看哪条链能处理该请求就将请求交给此链处理,其他链不再处理。
WebSecurityConfiguration
WebSecurity的构建是由它触发的。在前面我们知道,这个配置类是被@EnableWebSecurity注解导入的。
@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();
}
分析构建过程:
1、WebSecurityConfiguration 触发了构建过程
2、AbstractSecurityBuilder 保证在多线程情况下只构建一次
3、AbstractConfiguredSecurityBuilder 定义了构建的模版
4、WebSecurityConfigurerAdapter是构建时要使用的配置类(其中init()方法创建了HttpSecurity)
5、WebSecurity负责最终构建出FilterChainProxy
6、最终WebSecurityConfiguration将它放在容器中准备接受委派。
HttpSecurity
它是为了构建过滤器链。即:DefaultSecurityFilterChain。DefaultSecurityFilterChain才是真正用来处理请求的。所以用到了很多组件。
看它的构建过程:
这个是重点,后面详细讨论。