Spring Security本质是一个过滤器链
过滤器链本质是责任链设计模型
1. HttpSecurity
【第五篇】深入理解HttpSecurity的设计-腾讯云开发者社区-腾讯云
在以前spring security也是采用xml配置的方式,在<http>标签中配置http请求相关的配置,如用户权限等。但是在SpringBoot项目中,我们慢慢脱离了xml配置文件的方式,在SpringSecurity中提供了HttpSecurity等工具类。
1.1. SecurityBuilder
该接口仅定义了Spring Security构建对象的接口方法,是一个泛型接口,泛型中指明需要创建的对象。
public interface SecurityBuilder<O> {
/**
* Builds the object and returns it or null.
* @return the Object to be built or null if the implementation allows it.
* @throws Exception if an error occurred when building the Object
*/
O build() throws Exception;
}
1.2. AbstractSecurityBuilder
一个抽象实现类,该类确保对象仅被创建一次。使用了AtomicBoolean原子类,使该类在并发情况下也能保证正确性。
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {
private AtomicBoolean building = new AtomicBoolean();
private O object;
@Override
public final O build() throws Exception {
if (this.building.compareAndSet(false, true)) {
this.object = doBuild();
return this.object;
}
throw new AlreadyBuiltException("This object has already been built");
}
public final O getObject() {
if (!this.building.get()) {
throw new IllegalStateException("This object has not been built");
}
return this.object;
}
protected abstract O doBuild() throws Exception;
}
1.3. AbstractConfiguredSecurityBuilder
其内部了定义了一个枚举类,将整个构建过程分为 5 种状态,也可以理解为构建过程生命周期的五个阶段,如下:
private enum BuildState {
UNBUILT(0),
INITIALIZING(1),
CONFIGURING(2),
BUILDING(3),
BUILT(4);
private final int order;
BuildState(int order) {
this.order = order;
}
public boolean isInitializing() {
return INITIALIZING.order == this.order;
}
/**
* Determines if the state is CONFIGURING or later
* @return
*/
public boolean isConfigured() {
return this.order >= CONFIGURING.order;
}
}
构建过程:
@Override
protected final O doBuild() throws Exception {
synchronized (this.configurers) {
this.buildState = BuildState.INITIALIZING;
beforeInit(); //是一个预留方法,没有任何实现
init(); // 就是找到所有的 xxxConfigure,挨个调用其 init 方法进行初始化
this.buildState = BuildState.CONFIGURING;
beforeConfigure(); // 是一个预留方法,没有任何实现
configure(); // 就是找到所有的 xxxConfigure,挨个调用其 configure 方法进行配置。
this.buildState = BuildState.BUILDING;
// 是真正的过滤器链构建方法,
//但是在 AbstractConfiguredSecurityBuilder中 performBuild 方法只是一个抽象方法,
//具体的实现在 HttpSecurity 中
O result = performBuild();
this.buildState = BuildState.BUILT;
return result;
}
}
AbstractConfiguredSecurityBuilder
类字段中保存了一个配置列表,由HashMap存储了配置类和对应的配置列表,提供了添加、移除配置的方法。
private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<>();
2. SecurityConfigurer
public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {
void init(B builder) throws Exception;
void configure(B builder) throws Exception;
}
SecurityConfigurer<O, B>: 这是接口的声明,它指定了两个泛型参数。
- O:代表配置的目标对象(例如,配置安全性规则的目标对象)。这个参数表示你要对哪种类型的对象进行配置,例如,Web安全性规则(HttpSecurity)或认证管理器(AuthenticationManager)等。
- B:代表用于构建配置的构建器(builder)。这个参数表示你使用的构建器的类型,通常是一个实现了SecurityBuilder接口的类,用于构建和配置目标对象。
接口SecurityConfigurer定义了一种通用的配置模式,用于配置各种不同类型的安全对象,而泛型参数O和B允许它变得灵活并适用于不同的配置场景。当你实现SecurityConfigurer接口时,你会为不同的安全配置提供具体的实现,其中O表示你要配置的安全对象的类型,B表示你要使用的构建器类型。