WebSecurityConfigurerAdapter已废弃,官方推荐使用HttpSecurity 或WebSecurity。
都继承了SecurityBuilder
public interface SecurityBuilder<O> {
O build() throws Exception;
}
亮点:通过这种方式很容易知道知道自己构建的Object
HttpSecurity
public interface SecurityFilterChain {
/**
** 判断请求是否能够匹配上这些过滤器
**/
boolean matches(HttpServletRequest request);
/**
** 过滤器列表
**/
List<Filter> getFilters();
}
AbstractSecurityBuilder.class 用途:确保仅构建1次,调用子类的doBuild方法去构建对象
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");
}
/**
* Gets the object that was built. If it has not been built yet an Exception is
* thrown.
* @return the Object that was 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;
}
AbstractConfiguredSecurityBuilder.class
扩展点:beforeInit、beforeConfigure
@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;
}
}
protected void beforeInit() throws Exception {
}
protected void beforeConfigure() throws Exception {
}
/**
* 重要方法
**/
protected abstract O performBuild() throws Exception;
@SuppressWarnings("unchecked")
private void init() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.init((B) this);
}
for (SecurityConfigurer<O, B> configurer : this.configurersAddedInInitializing) {
configurer.init((B) this);
}
}
AbstractConfiguredSecurityBuilder.class
private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<>();
// 初始化添加的过滤器
private final List<SecurityConfigurer<O, B>> configurersAddedInInitializing = new ArrayList<>();
private final Map<Class<?>, Object> sharedObjects = new HashMap<>();
private final boolean allowConfigurersOfSameType;
// 构建状态
private BuildState buildState = BuildState.UNBUILT;
// 后置处理
private ObjectPostProcessor<Object> objectPostProcessor;
private <C extends SecurityConfigurer<O, B>> void add(C configurer) {
Assert.notNull(configurer, "configurer cannot be null");
Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
.getClass();
synchronized (this.configurers) {
if (this.buildState.isConfigured()) {
throw new IllegalStateException("Cannot apply " + configurer + " to already built object");
}
List<SecurityConfigurer<O, B>> configs = null;
if (this.allowConfigurersOfSameType) {
configs = this.configurers.get(clazz);
}
configs = (configs != null) ? configs : new ArrayList<>(1);
configs.add(configurer);
this.configurers.put(clazz, configs);
// 如果正在初始化往里面添加configurer,会在doBuild方法中使用
if (this.buildState.isInitializing()) {
this.configurersAddedInInitializing.add(configurer);
}
}
}
HttpSecurity.class
@Override
protected void beforeConfigure() throws Exception {
if (this.authenticationManager != null) {
setSharedObject(AuthenticationManager.class, this.authenticationManager);
}
else {
setSharedObject(AuthenticationManager.class, getAuthenticationRegistry().build());
}
}
private void configure() throws Exception {
Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
for (SecurityConfigurer<O, B> configurer : configurers) {
configurer.configure((B) this);
}
}
performBuild方法
WebSecurity.java 本质上一个FilterChainProxy
@Override
protected Filter performBuild() throws Exception {
......
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
......
Filter result = filterChainProxy;
if (this.debugEnabled) {
.....
result = new DebugFilter(filterChainProxy);
}
return result;
}
可以通过@EnableWebSecurity(debug = true)开启debug模式
new DebugFilter(filterChainProxy)对filterChainProxy进行装饰
public FilterChainProxy(List<SecurityFilterChain> filterChains) {
this.filterChains = filterChains;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
......
doFilterInternal(request, response, chain);
......
}
private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// HttpFirewall实例用于验证传入请求并创建包装请求,该请求提供一致的路径值以进行匹配。
FirewalledRequest firewallRequest = this.firewall.getFirewalledRequest((HttpServletRequest) request);
// 获取到匹配的filter
List<Filter> filters = getFilters(firewallRequest);
......
// 虚拟过滤器,挨个应用filters
VirtualFilterChain virtualFilterChain = new VirtualFilterChain(firewallRequest, chain, filters);
virtualFilterChain.doFilter(firewallRequest, firewallResponse);
}
// 获取匹配的filter
private List<Filter> getFilters(HttpServletRequest request) {
int count = 0;
for (SecurityFilterChain chain : this.filterChains) {
......
if (chain.matches(request)) {
return chain.getFilters();
}
}
return null;
}
// 虚拟过滤器,挨个应用filters
@Override
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if (this.currentPosition == this.size) {
if (logger.isDebugEnabled()) {
logger.debug(LogMessage.of(() -> "Secured " + requestLine(this.firewalledRequest)));
}
// Deactivate path stripping as we exit the security filter chain
this.firewalledRequest.reset();
this.originalChain.doFilter(request, response);
return;
}
this.currentPosition++;
Filter nextFilter = this.additionalFilters.get(this.currentPosition - 1);
if (logger.isTraceEnabled()) {
logger.trace(LogMessage.format("Invoking %s (%d/%d)", nextFilter.getClass().getSimpleName(),
this.currentPosition, this.size));
}
nextFilter.doFilter(request, response, this);
}
HttpSecurity.java
@SuppressWarnings("unchecked")
@Override
protected DefaultSecurityFilterChain performBuild() {
......
// 确保其中一个为null
boolean oneConfigurerPresent = expressionConfigurer == null ^ httpConfigurer == null;
return new DefaultSecurityFilterChain(this.requestMatcher, sortedFilters);
}
饿汉模式创建的一个任意请求匹配器,matches返回的都是true