美文网首页
SpringSecurity 启动流程

SpringSecurity 启动流程

作者: 昼暗 | 来源:发表于2020-03-07 19:39 被阅读0次

    一. 大概流程

    • 开启注解@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<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;
        // @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers
        // 这个参数this.beanFactory.getBeansOfType(WebSecurityConfigurer.class);
        // 实际是获取WebSecurityConfigurer的bean列表
        // 通过debug可以看到这里就是 我们自定义的配置,如果有OAuth2的话 还会看到AuthorizationServerSecurityConfiguration, ResourceServerConfiguration
        @Autowired(required = false)
        public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor, @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> 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<SecurityConfigurer<O, B>> 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<Class<? extends Object>, 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<AbstractHttpConfigurer> 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<? extends SecurityFilterChain> 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<SecurityFilterChain> 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<? extends SecurityFilterChain> 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 启动流程

          本文链接:https://www.haomeiwen.com/subject/zhphdhtx.html