Spring Security的启动流程

Spring Security在启动阶段会注册一些bean,并构建过滤器链,Spring Security的“安全”功能都是封装在该过滤器链中的。一般我们会根据业务需求向bean容器中注册一个过滤器链bean,该bean对象在启动阶段会被扫描到,并设置到相应的组件中。


SecurityFilterAutoConfiguration

该类是Spring Boot中提供的一个自动配置类,在该类中会注册一个特殊的bean,该bean会向servlet上下文中注册Spring Security中使用的过滤器。

v2.7.x
java
spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/servlet/SecurityFilterAutoConfiguration.java
@AutoConfiguration(after = SecurityAutoConfiguration.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(SecurityProperties.class)
@ConditionalOnClass({ AbstractSecurityWebApplicationInitializer.class, SessionCreationPolicy.class })
public class SecurityFilterAutoConfiguration {

	private static final String DEFAULT_FILTER_NAME = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME;

	@Bean
	/*
	 * 存在名为springSecurityFilterChain的bean时才注册该bean,
	 * WebSecurityConfiguration中会注册该bean
	 */
	@ConditionalOnBean(name = DEFAULT_FILTER_NAME)
	public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration(
			SecurityProperties securityProperties) {
		// 创建注册对象,该对象是一个servlet上下文初始化器,会创建并注册DelegatingFilterProxy这个特殊的过滤器
		DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean(
				DEFAULT_FILTER_NAME);
		registration.setOrder(securityProperties.getFilter().getOrder());
		registration.setDispatcherTypes(getDispatcherTypes(securityProperties));
		return registration;
	}

	private EnumSet<DispatcherType> getDispatcherTypes(SecurityProperties securityProperties) {
		if (securityProperties.getFilter().getDispatcherTypes() == null) {
			return null;
		}
		return securityProperties.getFilter().getDispatcherTypes().stream()
				.map((type) -> DispatcherType.valueOf(type.name()))
				.collect(Collectors.toCollection(() -> EnumSet.noneOf(DispatcherType.class)));
	}

}

DelegatingFilterProxyRegistrationBean是一个RegistrationBean,在介绍Spring Boot中DispatcherServlet注册时,就讲到Spring Boot也是通过RegistrationBean来注册的servlet。而RegistrationBean是一个servlet上下文初始化器,当servlet容器准备好servlet上下文时,会调用servlet上下文初始化器的onStartup方法。

v2.7.x
RegistrationBean
DynamicRegistrationBean
AbstractFilterRegistrationBean
getFilter
<
>
java
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/RegistrationBean.java
// Servlet上下文初始化后会调用该方法
@Override
public final void onStartup(ServletContext servletContext) throws ServletException {
    String description = getDescription();
    if (!isEnabled()) {
        logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
        return;
    }
    // 执行注册servlet的操作
    register(description, servletContext);
}
protected abstract void register(String description, ServletContext servletContext);
java
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/DynamicRegistrationBean.java
@Override
protected final void register(String description, ServletContext servletContext) {
    // 执行注册servlet的操作
    D registration = addRegistration(description, servletContext);
    if (registration == null) {
        logger.info(StringUtils.capitalize(description) + " was not registered (possibly already registered?)");
        return;
    }
    configure(registration);
}
protected abstract D addRegistration(String description, ServletContext servletContext);
java
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/AbstractFilterRegistrationBean.java
@Override
protected Dynamic addRegistration(String description, ServletContext servletContext) {
    // 获取过滤器,模板方法,由子类实现
    Filter filter = getFilter();
    // 注册过滤器到servlet上下文中
    return servletContext.addFilter(getOrDeduceName(filter), filter);
}
public abstract T getFilter();
java
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/DelegatingFilterProxyRegistrationBean.java
@Override
public DelegatingFilterProxy getFilter() {
    /*
     * 创建DelegatingFilterProxy对象,这个过滤器会被注册到servlet上下文中,是Spring Security的入口点
     * 这里的targetBeanName的值是springSecurityFilterChain,参考SecurityFilterAutoConfiguration类。
     */
    return new DelegatingFilterProxy(this.targetBeanName, getWebApplicationContext()) {

        @Override
        protected void initFilterBean() throws ServletException {
            // Don't initialize filter bean on init()
        }

    };
}

上面的调用链比较长,最终在DelegatingFilterProxyRegistrationBeangetFilter方法中,创建了过滤器。DelegatingFilterProxy是一个过滤器代理,是一个特殊的过滤器,是Spring Framework中提供的类。通过构造器设置了目标过滤器bean的名称,在SecurityFilterAutoConfiguration中可以发现,是定义在AbstractSecurityWebApplicationInitializer中的属性。

java
web/src/main/java/org/springframework/security/web/context/AbstractSecurityWebApplicationInitializer.java
public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";

好了,Spring Boot中的配置就结束了,主要是创建并设置DelegatingFilterProxy这个特殊的过滤器到servlet上下文中。

WebSecurityConfiguration

这是Spring Security中的一个配置类,会被Spring Framework中的ConfigurationClassPostProcess扫描到并处理。在该类中注册了上面创建的DelegatingFilterProxy中的目标过滤器。

java
config/src/main/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.java
// 注入spring security的过滤器链,在DelegatingFilterChain中会被调用
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
    /*
     * 一般来说,我们都会自定义一个过滤器链并注册到bean工厂中。那么这里就会使用我们配置好的,
     * 如果没有配置,则会使用默认的。
     * 当然我们自定义过滤器链还是会通过HttpSecurity来构建。
     */
    boolean hasFilterChain = !this.securityFilterChains.isEmpty();
    if (!hasFilterChain) { // this.securityFilterChains是空的情况
        // 添加默认的过滤器链
        this.webSecurity.addSecurityFilterChainBuilder(() -> {
            this.httpSecurity.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated());
            this.httpSecurity.formLogin(Customizer.withDefaults());
            this.httpSecurity.httpBasic(Customizer.withDefaults());
            return this.httpSecurity.build();
        });
    }
    // this.securityFilterChains不为空的情况

    // 一般我们会自定义过滤器链,所以这里会添加到webSecurity中
    for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
        this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
    }
    // 遍历自定义扩展器
    for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
        // 执行自定义操作
        customizer.customize(this.webSecurity);
    }
    // 构建过滤器
    return this.webSecurity.build();
}

一般我们会根据业务自定义并注册一个SecurityFilterChain类型的bean,在上面的方法中会被添加到WebSecurity对象中。最后通过WebSecurity来构建过滤器。

WebSecurity

AbstractSecurityBuilder

build方法的实现在父类AbstractSecurityBuilder中。

java
config/src/main/java/org/springframework/security/config/annotation/AbstractSecurityBuilder.java
public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O> {

	private AtomicBoolean building = new AtomicBoolean();

	private O object;

	@Override
	public final O build() throws Exception {
		// 通过CAS来保证不要重复构建
		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;
	}

	/**
	 * Subclasses should implement this to perform the build.
	 * @return the object that should be returned by {@link #build()}.
	 * @throws Exception if an error occurs
	 */
	protected abstract O doBuild() throws Exception;
}

AbstractSecurityBuilder不仅是WebSecurity的父类,还是HttpSecurity的父类。

AbstractConfiguredSecurityBuilder

子类AbstractConfiguredSecurityBuilder中实现了doBuild方法。

java
config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java
@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 abstract O performBuild() throws Exception;

实际的构建操作在子类实现的performBuild方法中,子类WebSecurityHttpSecurtiy都实现了这个方法。先来看WebSecurity中的实现。

WebSecurity

java
config/src/main/java/org/springframework/security/config/annotation/web/builders/WebSecurity.java
@Override
protected Filter performBuild() throws Exception {
    Assert.state(!this.securityFilterChainBuilders.isEmpty(),
            () -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "
                    + "Typically this is done by exposing a SecurityFilterChain bean. "
                    + "More advanced users can invoke " + WebSecurity.class.getSimpleName()
                    + ".addSecurityFilterChainBuilder directly");

    // 可以看出,有两类的filterChain
    int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
    // filterChain集合
    List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);
    List<RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>>> requestMatcherPrivilegeEvaluatorsEntries = new ArrayList<>();
    //
    for (RequestMatcher ignoredRequest : this.ignoredRequests) {
        WebSecurity.this.logger.warn("You are asking Spring Security to ignore " + ignoredRequest
                + ". This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.");
        // 创建过滤器链
        SecurityFilterChain securityFilterChain = new DefaultSecurityFilterChain(ignoredRequest);
        // 添加到列表中
        securityFilterChains.add(securityFilterChain);
        requestMatcherPrivilegeEvaluatorsEntries
            .add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
    }
    for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
        // 获取过滤器链
        SecurityFilterChain securityFilterChain = securityFilterChainBuilder.build();
        // 添加到列表中
        securityFilterChains.add(securityFilterChain);
        requestMatcherPrivilegeEvaluatorsEntries
            .add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
    }
    if (this.privilegeEvaluator == null) {
        this.privilegeEvaluator = new RequestMatcherDelegatingWebInvocationPrivilegeEvaluator(
                requestMatcherPrivilegeEvaluatorsEntries);
    }
    /*
     * 创建过滤器,DelegatingFilterProxy中的目标过滤器就是这个对象。
     */
    FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
    // 设置http防火墙
    if (this.httpFirewall != null) {
        filterChainProxy.setFirewall(this.httpFirewall);
    }
    // 设置请求拒绝处理器
    if (this.requestRejectedHandler != null) {
        filterChainProxy.setRequestRejectedHandler(this.requestRejectedHandler);
    }
    else if (!this.observationRegistry.isNoop()) {
        CompositeRequestRejectedHandler requestRejectedHandler = new CompositeRequestRejectedHandler(
                new ObservationMarkingRequestRejectedHandler(this.observationRegistry),
                new HttpStatusRequestRejectedHandler());
        filterChainProxy.setRequestRejectedHandler(requestRejectedHandler);
    }
    // 设置修饰器
    filterChainProxy.setFilterChainDecorator(getFilterChainDecorator());
    // bean的生命周期相关方法
    filterChainProxy.afterPropertiesSet();

    Filter result = filterChainProxy;
    if (this.debugEnabled) {
        this.logger.warn("\n\n" + "********************************************************************\n"
                + "**********        Security debugging is enabled.       *************\n"
                + "**********    This may include sensitive information.  *************\n"
                + "**********      Do not use in a production system!     *************\n"
                + "********************************************************************\n\n");
        result = new DebugFilter(filterChainProxy);
    }

    this.postBuildAction.run();
    return result;
}

在该方法中,先是合并了两类过滤器链,然后创建并初始化了FilterChainProxy对象,这个对象就是最终注册到bean工厂中的bean,也是Spring Security中DelegatingFilterProxy的目标过滤器。

DelegatingFilterProxy的初始化

DelegatingFilterProxy是继承了GenericFilterBean,后者实现了Filter接口。所以在初始化的时候会调用GenericFilterBeaninit方法,而该方法又会调用DelegatingFilterProxy实现的initFilterBean方法。

java
spring-web/src/main/java/org/springframework/web/filter/DelegatingFilterProxy.java
@Override
protected void initFilterBean() throws ServletException {
    synchronized (this.delegateMonitor) {
        // 没有设置才获取,即调用的参数是字符串的构造方法才会执行
        if (this.delegate == null) {
            // If no target bean name specified, use filter name.
            if (this.targetBeanName == null) {
                this.targetBeanName = getFilterName();
            }
            // Fetch Spring root application context and initialize the delegate early,
            // if possible. If the root application context will be started after this
            // filter proxy, we'll have to resort to lazy initialization.
            WebApplicationContext wac = findWebApplicationContext();
            if (wac != null) {
                // 从应用上下文中获取目标过滤器
                this.delegate = initDelegate(wac);
            }
        }
    }
}
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
    String targetBeanName = getTargetBeanName();
    Assert.state(targetBeanName != null, "No target bean name set");
    // 获取目标过滤器bean对象
    Filter delegate = wac.getBean(targetBeanName, Filter.class);
    if (isTargetFilterLifecycle()) {
        delegate.init(getFilterConfig());
    }
    return delegate;
}

在上面已经介绍过了,这里获取到的bean是FilterChainProxy类型的。

通过HttpSecurity自定义过滤器链

在5.x中,一般会创建一个配置类,并继承WebSecurityConfigurerAdapter,并重写该类中的configure方法, 该方法的唯一参数就是configure,然后基于该类来配置。 在6.x版本中,直接向容器中注册SecurityFilterChain就行了,当然也是通过该类来创建过滤器链。 在HttpSecurityConfiguration配置类中会创建并注册HttpSecurity,所以可以在用户自定义的配置类中注入该bean。

java
config/src/main/java/org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.java
// 注入httpSecurity
@Bean(HTTPSECURITY_BEAN_NAME)
@Scope("prototype")
HttpSecurity httpSecurity() throws Exception {
    // 创建密码编码器
    LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context);
    // 构造认证管理器的构建器
    AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(
            this.objectPostProcessor, passwordEncoder);
    // 添加认证管理器
    authenticationBuilder.parentAuthenticationManager(authenticationManager());
    authenticationBuilder.authenticationEventPublisher(getAuthenticationEventPublisher());

    // 构建HttpSecurity对象
    HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
    WebAsyncManagerIntegrationFilter webAsyncManagerIntegrationFilter = new WebAsyncManagerIntegrationFilter();
    webAsyncManagerIntegrationFilter.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
    // @formatter:off
    /*
     * 一系列默认配置,其实这里都是在往HttpSecurity对象中添加各种配置器(configurer),配置器又对应了各种filter
     * 我们会通过http.build()方法来获取SecurityFilterChain对象,在build之前会执行beforeInit、init、beforeConfigure、configure一系列的方法,
     * 在configure方法中会往httpSecurity对象中添加过滤器,然后build的时候会将这些过滤器进行排序,然后传递到DefaultSecurityFilterChain的构造器中
     */
    http
        .csrf(withDefaults())
        .addFilter(webAsyncManagerIntegrationFilter)
        .exceptionHandling(withDefaults())
        .headers(withDefaults())
        .sessionManagement(withDefaults())
        .securityContext(withDefaults())
        .requestCache(withDefaults())
        .anonymous(withDefaults())
        .servletApi(withDefaults())
        .apply(new DefaultLoginPageConfigurer<>());
    http.logout(withDefaults());
    // @formatter:on
    applyDefaultConfigurers(http);
    return http;
}

上面方法中创建了HttpSecurity对象,并为其添加了默认配置,可以在业务实现中覆盖默认设置。

构建过滤器链

java
config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
@SuppressWarnings("unchecked")
@Override
protected DefaultSecurityFilterChain performBuild() {
    // URL表达式授权配置器
    ExpressionUrlAuthorizationConfigurer<?> expressionConfigurer = getConfigurer(
            ExpressionUrlAuthorizationConfigurer.class);
    // http授权配置器
    AuthorizeHttpRequestsConfigurer<?> httpConfigurer = getConfigurer(AuthorizeHttpRequestsConfigurer.class);
    // 这里使用了异或运算符(^)
    boolean oneConfigurerPresent = expressionConfigurer == null ^ httpConfigurer == null;
    // 如果都为null或都不为null,则断言失败,请选一个使用
    Assert.state((expressionConfigurer == null && httpConfigurer == null) || oneConfigurerPresent,
            "authorizeHttpRequests cannot be used in conjunction with authorizeRequests. Please select just one.");

    // 对过滤器进行排序
    this.filters.sort(OrderComparator.INSTANCE);
    List<Filter> sortedFilters = new ArrayList<>(this.filters.size());
    for (Filter filter : this.filters) {
        // 添加到列表中
        sortedFilters.add(((OrderedFilter) filter).filter);
    }
    // 创建过滤器链
    return new DefaultSecurityFilterChain(this.requestMatcher, sortedFilters);
}

这里创建的是DefaultSecurityFilterChain类型的对象,封装了实例属性filters。那么个filters属性中的过滤器是哪里来的?

调用配置器

一般我们会调用HttpSecurity中的方法并传入自定义器来实现扩展,好像并没有创建和添加过滤器,实际上这个奥秘就在配置器中。因为Spring Security支持太多种类型的配置器了,所以这里以HeadersConfigurer为例。

java
config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
public HttpSecurity headers(Customizer<HeadersConfigurer<HttpSecurity>> headersCustomizer) throws Exception {
    headersCustomizer.customize(getOrApply(new HeadersConfigurer<>()));
    return HttpSecurity.this;
}
java
config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
@SuppressWarnings("unchecked")
private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(C configurer)
        throws Exception {
    // 获取配置器
    C existingConfig = (C) getConfigurer(configurer.getClass());
    // 如果已经存在相同类型的
    if (existingConfig != null) {
        // 则直接返回
        return existingConfig;
    }
    // 添加配置器
    return apply(configurer);
}

getConfigurer方法和apply方法都定义在父类AbstractConfiguredSecurityBuilder中。

java
config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java
private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<>();
@SuppressWarnings("unchecked")
public <C extends SecurityConfigurer<O, B>> C getConfigurer(Class<C> clazz) {
    List<SecurityConfigurer<O, B>> configs = this.configurers.get(clazz);
    if (configs == null) {
        return null;
    }
    Assert.state(configs.size() == 1,
            () -> "Only one configurer expected for type " + clazz + ", but got " + configs);
    return (C) configs.get(0);
}
@SuppressWarnings("unchecked")
public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer) throws Exception {
    configurer.addObjectPostProcessor(this.objectPostProcessor);
    configurer.setBuilder((B) this);
    // 添加配置器
    add(configurer);
    return configurer;
}
@SuppressWarnings("unchecked")
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);
        }
    }
}

这样看起来好像getOrApply只是添加了配置器而已,还是没有找到过滤器的踪影。其实在调用build时,在执行performBuild方法之前,还执行doBuild方法,在该方法中调用了initconfigure等方法。

java
config/src/main/java/org/springframework/security/config/annotation/AbstractConfiguredSecurityBuilder.java
@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;
    }
}
	@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);
		}
	}
	@SuppressWarnings("unchecked")
	private void configure() throws Exception {
		Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
		for (SecurityConfigurer<O, B> configurer : configurers) {
			configurer.configure((B) this);
		}
	}

上面调用了每个配置器的initconfigure方法。

对于HeadersConfigurer,重写了configure方法,并创建和注册了过滤器。

java
config/src/main/java/org/springframework/security/config/annotation/web/configurers/HeadersConfigurer.java
// 这里的http就是就是HttpSecurity
@Override
public void configure(H http) {
    HeaderWriterFilter headersFilter = createHeaderWriterFilter();
    http.addFilter(headersFilter);
}
private HeaderWriterFilter createHeaderWriterFilter() {
    List<HeaderWriter> writers = getHeaderWriters();
    if (writers.isEmpty()) {
        throw new IllegalStateException(
                "Headers security is enabled, but no headers will be added. Either add headers or disable headers security");
    }
    // 创建过滤器
    HeaderWriterFilter headersFilter = new HeaderWriterFilter(writers);
    headersFilter = postProcess(headersFilter);
    return headersFilter;
}

有的配置器是在init方法中创建过滤器,然后在configure方法中添加过滤器。反正不同的配置器的逻辑过滤器创建和添加逻辑都差不过。

最后调用HttpSecurityaddFilter方法来添加过滤器。

java
config/src/main/java/org/springframework/security/config/annotation/web/builders/HttpSecurity.java
@Override
public HttpSecurity addFilter(Filter filter) {
    // 这里添加的filter必须是官方定义的,否则会报错
    Integer order = this.filterOrders.getOrder(filter.getClass());
    if (order == null) {
        throw new IllegalArgumentException("The Filter class " + filter.getClass().getName()
                + " does not have a registered order and cannot be added without a specified order. Consider using addFilterBefore or addFilterAfter instead.");
    }
    // 封装为OrderedFilter,并添加到属性列表中
    this.filters.add(new OrderedFilter(filter, order));
    return this;
}

这样就知道了performBuild方法中的过滤器列表是哪里来的了。当然除了配置器,也可以直接调用HttpSecurityaddFilter方法来添加过滤器。

总结

HttpSecurity中定义了很多规则方法,每个方法的参数是一个定制化器,主要是对配置器进行定制化,定制化器中可以修改配置器中的属性来实现自定义。在构建过滤器之前,会调用各个配置器的initconfigure方法来创建和添加过滤器,最后构建时,将所有的过滤器封装为一条过滤器链。