SpringSecurity 启动流程

一. 大概流程

  • 开启注解@EnableWebSecurity
  • 启动后开始配置SpringSecurity
  • 获取当前WebSecurityConfigurer的子类,构造出WebSecurity(用于生成filter)
  • 初始化WebSecurityConfigurer的子类,构造出对应HttpSecurity
  • HttpSecurity构造出DefaultSecurityFilterChain(包含属性 请求matcher以及对应过滤器的列表)
  • DefaultSecurityFilterChain构建FilterChainProxy
  • FilterChainProxy是SpringSecurity的过滤器链。(依次matcher请求,如果匹配执行对应过滤器列表)

二. 具体代码

  1. 开启注解@EnableWebSecurity
@Import({WebSecurityConfiguration.class, SpringWebMvcImportSelector.class})
  1. WebSecurityConfiguration
@Configuration
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
    private WebSecurity webSecurity;
    private List> webSecurityConfigurers;
    // @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List> webSecurityConfigurers
    // 这个参数this.beanFactory.getBeansOfType(WebSecurityConfigurer.class);
    // 实际是获取WebSecurityConfigurer的bean列表
    // 通过debug可以看到这里就是 我们自定义的配置,如果有OAuth2的话 还会看到AuthorizationServerSecurityConfiguration, ResourceServerConfiguration
    @Autowired(required = false)
    public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor objectPostProcessor, @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List> webSecurityConfigurers) throws Exception {
        // 创建WebSecurity
        this.webSecurity = (WebSecurity)objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
        if (this.debugEnabled != null) {
            this.webSecurity.debug(this.debugEnabled);
        }

        Collections.sort(webSecurityConfigurers, WebSecurityConfiguration.AnnotationAwareOrderComparator.INSTANCE);
        Integer previousOrder = null;
        Object previousConfig = null;

        Iterator var5;
        SecurityConfigurer config;
        for(var5 = webSecurityConfigurers.iterator(); var5.hasNext(); previousConfig = config) {
            config = (SecurityConfigurer)var5.next();
            Integer order = WebSecurityConfiguration.AnnotationAwareOrderComparator.lookupOrder(config);
            if (previousOrder != null && previousOrder.equals(order)) {
                throw new IllegalStateException("@Order on WebSecurityConfigurers must be unique. Order of " + order + " was already used on " + previousConfig + ", so it cannot be used on " + config + " too.");
            }

            previousOrder = order;
        }

        var5 = webSecurityConfigurers.iterator();
        // 将配置添加到WebSecurity中, 后续执行建造时会用到
        while(var5.hasNext()) {
            config = (SecurityConfigurer)var5.next();
            this.webSecurity.apply(config);
        }

        this.webSecurityConfigurers = webSecurityConfigurers;
    }
  
    
    @Bean(
        name = {"springSecurityFilterChain"}
    )
    public Filter springSecurityFilterChain() throws Exception {
        boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
        if (!hasConfigurers) {
            WebSecurityConfigurerAdapter adapter = (WebSecurityConfigurerAdapter)this.objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter() {
            });
            this.webSecurity.apply(adapter);
        }
        // 真正开始建造Filter
        return (Filter)this.webSecurity.build();
    }
}

  1. AbstractConfiguredSecurityBuilder build流程, 模版方法, WebSecurity和HttpSecurity建造时都会走这个流程
    protected final O doBuild() throws Exception {
        synchronized(this.configurers) {
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.INITIALIZING;
            this.beforeInit();
            this.init();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.CONFIGURING;
            this.beforeConfigure();
            this.configure();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILDING;
            O result = this.performBuild();
            this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILT;
            return result;
        }
    }
  1. beforeInit 和 beforeConfigure 是个空方法,所以跳过
  2. init方法
    5.1
    // 这里的configurers就是第二步中加载进来的 三个配置类
    // 1. 自定义的配置
    // 2. AuthorizationServerSecurityConfiguration
    // 3. ResourceServerConfiguration
    // 都是WebSecurityConfigurerAdapter的子类 所以去这个类看具体实现
    private void init() throws Exception {
        Collection> configurers = this.getConfigurers();
        Iterator var2 = configurers.iterator();

        SecurityConfigurer configurer;
        while(var2.hasNext()) {
            configurer = (SecurityConfigurer)var2.next();
            configurer.init(this);
        }

        var2 = this.configurersAddedInInitializing.iterator();

        while(var2.hasNext()) {
            configurer = (SecurityConfigurer)var2.next();
            configurer.init(this);
        }

    }

5.2. WebSecurityConfigurerAdapter

    public void init(final WebSecurity web) throws Exception {
        // 创建HttpSecurity
        final HttpSecurity http = this.getHttp();
        // 加入到WebSecurity中
        web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() {
            public void run() {
                FilterSecurityInterceptor securityInterceptor = (FilterSecurityInterceptor)http.getSharedObject(FilterSecurityInterceptor.class);
                web.securityInterceptor(securityInterceptor);
            }
        });
    }

    protected final HttpSecurity getHttp() throws Exception {
        if (this.http != null) {
            return this.http;
        } else {
            DefaultAuthenticationEventPublisher eventPublisher = (DefaultAuthenticationEventPublisher)this.objectPostProcessor.postProcess(new DefaultAuthenticationEventPublisher());
            this.localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
            AuthenticationManager authenticationManager = this.authenticationManager();
            this.authenticationBuilder.parentAuthenticationManager(authenticationManager);
            this.authenticationBuilder.authenticationEventPublisher(eventPublisher);
            Map, Object> sharedObjects = this.createSharedObjects();
            this.http = new HttpSecurity(this.objectPostProcessor, this.authenticationBuilder, sharedObjects);
            if (!this.disableDefaults) {
                // 这里给HttpSecurity加入了很多AbstractHttpConfigurer(看名字就是用了配置HttpSecurity的跟 WebSecurity类似)的子类
                ((HttpSecurity)((DefaultLoginPageConfigurer)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)((HttpSecurity)this.http.csrf().and()).addFilter(new WebAsyncManagerIntegrationFilter()).exceptionHandling().and()).headers().and()).sessionManagement().and()).securityContext().and()).requestCache().and()).anonymous().and()).servletApi().and()).apply(new DefaultLoginPageConfigurer())).and()).logout();
                ClassLoader classLoader = this.context.getClassLoader();
                List defaultHttpConfigurers = SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
                Iterator var6 = defaultHttpConfigurers.iterator();

                while(var6.hasNext()) {
                    AbstractHttpConfigurer configurer = (AbstractHttpConfigurer)var6.next();
                    this.http.apply(configurer);
                }
            }
            
            this.configure(this.http);
            return this.http;
        }
    }
  1. configure()方法 跟init类似会进入WebSecurityConfigurerAdapter, 然而不同的是我们会实现这个方法,所以其实这个会走进我们自定的方法中
  2. build
    protected Filter performBuild() throws Exception {
        Assert.state(!this.securityFilterChainBuilders.isEmpty(), () -> {
            return "At least one SecurityBuilder needs to be specified. Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. More advanced users can invoke " + WebSecurity.class.getSimpleName() + ".addSecurityFilterChainBuilder directly";
        });
        int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
        List securityFilterChains = new ArrayList(chainSize);
        Iterator var3 = this.ignoredRequests.iterator();

        while(var3.hasNext()) {
            RequestMatcher ignoredRequest = (RequestMatcher)var3.next();
            securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest, new Filter[0]));
        }

        var3 = this.securityFilterChainBuilders.iterator();

        while(var3.hasNext()) {
            SecurityBuilder securityFilterChainBuilder = (SecurityBuilder)var3.next();
            // securityFilterChainBuilder上面构造init中构造出来的HttpSecurity加入进来了, 所以这里的build,就是在执行HttpSecurity的建造方法
            securityFilterChains.add(securityFilterChainBuilder.build());
        }

        FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
        if (this.httpFirewall != null) {
            filterChainProxy.setFirewall(this.httpFirewall);
        }

        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 (Filter)result;
    }
  1. FilterChainProxy最终的过滤器,其中会维护一个虚拟过滤器链

你可能感兴趣的:(SpringSecurity 启动流程)