• spring security 源码学习(四)SecurityFilterChain


    SecurityFilterChain是Spring security真正执行认证授权的类。这个类初始化是从HttpSecurity的build而来。也就是上篇文章securityFilterChainBuilder.build()处得来。为了省去翻到上一篇文章,我把必要的代码和类图传送过来。

        for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
          securityFilterChains.add(securityFilterChainBuilder.build());(1)
        }
    

      

     所以securityFilterChainBuilder.build()就是AbstractSecurityBuilder的build方法

    	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");
    	}
    

      doBuild()就是我们的老演员了,上篇文章也说过的模版方法

    	protected final O doBuild() throws Exception {
    		synchronized (configurers) {
    			buildState = BuildState.INITIALIZING;
    
    			beforeInit();
    			init();
    
    			buildState = BuildState.CONFIGURING;
    
    			beforeConfigure();
    			configure();
    
    			buildState = BuildState.BUILDING;
    
    			O result = performBuild();
    
    			buildState = BuildState.BUILT;
    
    			return result;
    		}
    	}
    

      同样的,让我们从init()开始

    	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 : configurersAddedInInitializing) {
    			configurer.init((B) this);
    		}
    	}
    

      这里的getConfigurers()是从哪来的呢?答案就在Httpsecurity初始化的时候,同样,我们把上一篇文章中getHttp()方法考过来。

    protected final HttpSecurity getHttp() throws Exception {
        if (http != null) {
            return http;
        }
     
        DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor
                .postProcess(new DefaultAuthenticationEventPublisher());
        localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
     
        AuthenticationManager authenticationManager = authenticationManager();(1)
        authenticationBuilder.parentAuthenticationManager(authenticationManager);
        Map<Class<? extends Object>, Object> sharedObjects = createSharedObjects();
     
        http = new HttpSecurity(objectPostProcessor, authenticationBuilder,
                sharedObjects);(2)
        if (!disableDefaults) {
            // @formatter:off
            http
                .csrf().and()(3)
                .addFilter(new WebAsyncManagerIntegrationFilter())(4)
                .exceptionHandling().and()(5)
                .headers().and()(6)
                .sessionManagement().and()(7)
                .securityContext().and()(8)
                .requestCache().and()(9)
                .anonymous().and()(10)
                .servletApi().and()(11)
                .apply(new DefaultLoginPageConfigurer<HttpSecurity>()).and()(12)
                .logout();(13)
            // @formatter:on
            ClassLoader classLoader = this.context.getClassLoader();
            List<AbstractHttpConfigurer> defaultHttpConfigurers =
                    SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);
     
            for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
                http.apply(configurer);
            }
        }
        configure(http);
        return http;
    }
    

      我们拿其中一个来看看。就拿开头的http.csrf();

    	public CsrfConfigurer<HttpSecurity> csrf() throws Exception {
    		ApplicationContext context = getContext();
    		return getOrApply(new CsrfConfigurer<HttpSecurity>(context));
    	}
    
    	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);
    	}
    

      

    	public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer)
    			throws Exception {
    		configurer.addObjectPostProcessor(objectPostProcessor);
    		configurer.setBuilder((B) this);
    		add(configurer);
    		return configurer;
    	}
    

      

    	private <C extends SecurityConfigurer<O, B>> void add(C configurer) throws Exception {
    		Assert.notNull(configurer, "configurer cannot be null");
    
    		Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
    				.getClass();
    		synchronized (configurers) {
    			if (buildState.isConfigured()) {
    				throw new IllegalStateException("Cannot apply " + configurer
    						+ " to already built object");
    			}
    			List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers
    					.get(clazz) : null;
    			if (configs == null) {
    				configs = new ArrayList<SecurityConfigurer<O, B>>(1);
    			}
    			configs.add(configurer);
    			this.configurers.put(clazz, configs);
    			if (buildState.isInitializing()) {
    				this.configurersAddedInInitializing.add(configurer);
    			}
    		}
    	}
    

      从上面的一连串的方法可以看出来,http.csrf()将new出来的CsrfConfigurer<HttpSecurity>(context)加入到了

    private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>>();
    

      也就是加入到了getConfigurers返回的List中。

    这里每个Configurer实际的init和config我们针对每个不同的Configurer都做一个专题走访,这里提供传送门

    configure filter 简述
    SecurityContextConfigurer
    SecurityContextPersistenceFilter
     
         
         
         
         
         
         
         
         
         
         

    最后我们看下performBuild方法

    	@Override
    	protected DefaultSecurityFilterChain performBuild() throws Exception {
    		Collections.sort(filters, comparator);
    		return new DefaultSecurityFilterChain(requestMatcher, filters);
    	}
    

      这里倒是比较简单,对上面的filters拍了个序,然后new出了DefaultSecurityFilterChain,这里注意下DefaultSecurityFilterChain构造器的两个参数

    	public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
    		logger.info("Creating filter chain: " + requestMatcher + ", " + filters);
    		this.requestMatcher = requestMatcher;
    		this.filters = new ArrayList<Filter>(filters);
    	}
    

      List<Filter> filters我们在上面已经分析过了,他们具体的形成我们后面细说,RequestMatcher requestMatcher这个参数的作用也是异常的大,他根据uri进行match判断,觉得了是否用这个HttpSecurity形成的FilterChain来对请求做处理。默认情况是

    	private RequestMatcher requestMatcher = AnyRequestMatcher.INSTANCE;
    

      也就是所有的我们都走认证,如果想要做配置,就可以在上一篇文章中讲的在配置中override这个方法

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                    .antMatchers("/", "/home").permitAll()
                    .anyRequest().authenticated()
                    .antMatchers("/aaa").authenticated()
                    .and()
                    .formLogin()
                    .loginPage("/login")
                    .permitAll()
                    .and()
                    .logout()
                    .permitAll();
        }
    

      

  • 相关阅读:
    Springboot演示小Demo
    快速构建一个 Springboot
    javase练习题--每天写写
    javase练习题
    WebDriver API——延时操作及元素等待
    WebDriver API——javascript的相关操作
    Jenkins安装部署及tomcat的入门介绍
    WebDriver API——鼠标及键盘操作Actions
    sql查询练习
    睡前反省,絮叨絮叨
  • 原文地址:https://www.cnblogs.com/vincentren/p/15721675.html
Copyright © 2020-2023  润新知