WebSecurityConfigurerAdapter已废弃,官方推荐使用HttpSecurity 或WebSecurity。
都继承了SecurityBuilder
public interface SecurityBuilder<O> {O build() throws Exception;}
亮点:通过这种方式很容易知道知道自己构建的Object
HttpSecurity
public interface SecurityFilterChain {/**** 判断请求是否能够匹配上这些过滤器**/boolean matches(HttpServletRequest request);/**** 过滤器列表**/List<Filter> getFilters();
}
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {private AtomicBoolean building = new AtomicBoolean();private O object;/*** 防止重复构建**/@Overridepublic 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;}
@Overrideprotected 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")@Overrideprotected DefaultSecurityFilterChain performBuild() {......return new DefaultSecurityFilterChain(this.requestMatcher, sortedFilters);}
@Overrideprotected 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;}@Overridepublic 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 {FirewalledRequest firewallRequest = this.firewall.getFirewalledRequest((HttpServletRequest) request);List<Filter> filters = getFilters(firewallRequest);......// 虚拟过滤器,挨个应用filtersVirtualFilterChain virtualFilterChain = new VirtualFilterChain(firewallRequest, chain, filters);virtualFilterChain.doFilter(firewallRequest, firewallResponse);}// 获取匹配的filterprivate List<Filter> getFilters(HttpServletRequest request) {int count = 0;for (SecurityFilterChain chain : this.filterChains) {......if (chain.matches(request)) {return chain.getFilters();}}return null;}
@Overridepublic 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 chainthis.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);}
AbstractConfiguredSecurityBuilder.classprivate 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);if (this.buildState.isInitializing()) {this.configurersAddedInInitializing.add(configurer);}}}
/*** 由于配置一个SecurityBuilder* Allows for configuring a {@link SecurityBuilder}. All {@link SecurityConfigurer} first* have their {@link #init(SecurityBuilder)} method invoked. After all* {@link #init(SecurityBuilder)} methods have been invoked, each* {@link #configure(SecurityBuilder)} method is invoked.** @param <O> The object being built by the {@link SecurityBuilder} B* @param <B> The {@link SecurityBuilder} that builds objects of type O. This is also the* {@link SecurityBuilder} that is being configured.* @author Rob Winch* @see AbstractConfiguredSecurityBuilder*/
public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {/*** 设置一些共享状态,而不是属性* Initialize the {@link SecurityBuilder}. Here only shared state should be created* and modified, but not properties on the {@link SecurityBuilder} used for building* the object. This ensures that the {@link #configure(SecurityBuilder)} method uses* the correct shared objects when building. Configurers should be applied here.* @param builder* @throws Exception*/void init(B builder) throws Exception;/*** Configure the {@link SecurityBuilder} by setting the necessary properties on the* {@link SecurityBuilder}.* @param builder* @throws Exception*/void configure(B builder) throws Exception;}
private enum BuildState {/*** This is the state before the {@link Builder#build()} is invoked*/UNBUILT(0),/*** The state from when {@link Builder#build()} is first invoked until all the* {@link SecurityConfigurer#init(SecurityBuilder)} methods have been invoked.*/INITIALIZING(1),/*** The state from after all {@link SecurityConfigurer#init(SecurityBuilder)} have* been invoked until after all the* {@link SecurityConfigurer#configure(SecurityBuilder)} methods have been* invoked.*/CONFIGURING(2),/*** From the point after all the* {@link SecurityConfigurer#configure(SecurityBuilder)} have completed to just* after {@link AbstractConfiguredSecurityBuilder#performBuild()}.*/BUILDING(3),/*** After the object has been completely built.*/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;}}