志宇-springSecurty

springSecurty启动流程


首先 EnableWebSecurity 注解导入了 WebSecurityConfiguration配置类

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,
		SpringWebMvcImportSelector.class,
		OAuth2ImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {}

首先看这个类org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration
代码如下

@Autowired(required = false)
	public void setFilterChainProxySecurityConfigurer(
			ObjectPostProcessor<Object> objectPostProcessor,
			@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
			throws Exception {
        //通过AutowireBeanFactoryObjectPostProcessor将WebSecurity注入到spring容器中
        //WebSecurity是AutowireBeanFactoryObjectPostProcessor的代理对象
		webSecurity = objectPostProcessor
				.postProcess(new WebSecurity(objectPostProcessor));
        //从spring容器中获得所有配置的WebSecurityConfigurerAdapter的类
        //WebSecurityConfigurerAdapter是我们配置的springSecurity要继承的类
        //调用他的apply方法
		for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
			//将WebSecurityConfigurerAdapter放到一个集合LinkedHashMap中
			webSecurity.apply(webSecurityConfigurer);
		}
		this.webSecurityConfigurers = webSecurityConfigurers;
	}

代码分析
上面代码会创建一个 AutowireBeanFactoryObjectPostProcessor的代理类 WebSecurity
WebSecurity这个类可以向spring容器添加对象,同时还维护着一个LinkedHashMap用来存储所有的WebSecurityConfigurerAdapterWebSecurityConfigurerAdapter是配置springSecurity要继承的类

接下来看这个类org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration
代码如下

@Bean(name = "springSecurityFilterChain")
public Filter springSecurityFilterChain() throws Exception {
	boolean hasConfigurers = webSecurityConfigurers != null
			&& !webSecurityConfigurers.isEmpty();
	if (!hasConfigurers) {
	//通过AutowireBeanFactoryObjectPostProcessor向spring容器注册WebSecurityConfigurerAdapter
		WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
				.postProcess(new WebSecurityConfigurerAdapter() {
				});
		webSecurity.apply(adapter);
	}
	//调用
	return webSecurity.build();
}

代码分析
上面代码会通过AutowireBeanFactoryObjectPostProcessor向spring容器注册一个对象WebSecurityConfigurerAdapter,然后将WebSecurityConfigurerAdapter存储到webSecurity中,
然后调用webSecuritybuild方法,执行代码如下

protected final O doBuild() throws Exception {
    //configurers 是webSecurity中存储WebSecurityConfigurerAdapter的LinkedHashMap
	synchronized (configurers) {
	   //通过枚举修改状态
		buildState = BuildState.INITIALIZING;
		//空方法 用于扩展
		beforeInit();
		//调用configurers集合中所有对象的init方法
		//当前集合中只有一个对象 WebSecurityConfigurerAdapter
		init();
		buildState = BuildState.CONFIGURING;
		
		beforeConfigure();
		//调用configurers集合中所有对象的configure方法
		configure();
		buildState = BuildState.BUILDING;
		
		O result = performBuild();
		buildState = BuildState.BUILT;

		return result;
	}
}

接下来依次分析 init()beforeConfigure()configure()performBuild()方法,WebSecurityConfigurerAdapter

此部分代码比较多分部分析,代码如下

public void init(final WebSecurity web) throws Exception {
	//创建一个HttpSecurity
	final HttpSecurity http = getHttp();
	web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
		FilterSecurityInterceptor securityInterceptor = http
				.getSharedObject(FilterSecurityInterceptor.class);
		//给WebSecurity设置一个拦截器
		web.securityInterceptor(securityInterceptor);
	});
	protected final HttpSecurity getHttp() throws Exception {
	    //首先创建DefaultAuthenticationEventPublisher对象然后将这个对象添加到spring容器中
	    //此对象维护着一个exceptionMappings对象,存储异常和ApplicationEvent
		DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor
				.postProcess(new DefaultAuthenticationEventPublisher());
        //将eventPublisher给localConfigureAuthenticationBldr代理
        //localConfigureAuthenticationBldr 也就是 AuthenticationManagerBuilder对象
		localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);
		AuthenticationManager authenticationManager = authenticationManager();
		authenticationBuilder.parentAuthenticationManager(authenticationManager);
		authenticationBuilder.authenticationEventPublisher(eventPublisher);
		Map<Class<?>, Object> sharedObjects = createSharedObjects();

		//创建http对象,其中FilterComparator中存储了32个过滤器	
		http = new HttpSecurity(objectPostProcessor, authenticationBuilder,
				sharedObjects);
		if (!disableDefaults) {
			// 往HttpSecurity添加一些列的 配置类
			//CsrfConfigurer
			//ExceptionHandlingConfigurer
			//HeadersConfigurer
			//SessionManagementConfigurer
			//SecurityContextConfigurer
			//RequestCacheConfigurer
			//AnonymousConfigurer
			//ServletApiConfigurer
			//DefaultLoginPageConfigurer
			//LogoutConfigurer
			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);
			//添加一些默认配置
			for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
				http.apply(configurer);
			}
		}
		//调用自己配置的 configure方法,添加一些Configurer
		configure(http);
		return http;
	}
	protected AuthenticationManager authenticationManager() throws Exception {
	    //这里仅仅用一个标志位不用锁 也不会线程不安全
	    //因为build 方法中通过  
	    //if(AtomicBoolean.compareAndSet(false, true)){}
		if (!authenticationManagerInitialized) {
		    //调用配置的configure方法
		    //方法中我们给 provider的 UserDetailsService,passwordEncoder 成员变量赋值
		    //同时添加DaoAuthenticationConfigurer 对象
			configure(localConfigureAuthenticationBldr);
			if (disableLocalConfigureAuthenticationBldr) {
        		//如果我们没有重写configure方法则调用这里逻辑
				authenticationManager = authenticationConfiguration
						.getAuthenticationManager();
			}
			else {
			    //localConfigureAuthenticationBldr 也就是 AuthenticationManagerBuilder对象
			    //AuthenticationManagerBuilder中的configurers中只有一个对象DaoAuthenticationConfigurer
			    //调用 DaoAuthenticationConfigurer 的doBuild方法
			    //方法中会通过包装创建一个ProviderManager
				authenticationManager = localConfigureAuthenticationBldr.build();
			}
			authenticationManagerInitialized = true;
		}
		return authenticationManager;
	}

    
	private void configure() throws Exception {
		Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
		//循环调用所有配置类的方法
		//有的configurer中的configure方法会添加拦截器
		for (SecurityConfigurer<O, B> configurer : configurers) {
			configurer.configure((B) this);
		}
	}

	protected Filter performBuild() throws Exception {
		Assert.state(
				!securityFilterChainBuilders.isEmpty(),
				() -> "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 = ignoredRequests.size() + securityFilterChainBuilders.size();
		List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
				chainSize);
		for (RequestMatcher ignoredRequest : ignoredRequests) {
			securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
		}
		//securityFilterChainBuilder中存储所有的 HttpSecurity
		for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
		     //在方法中循环遍历所有HttpSecurity中configurers 
		     //configurers 是webSecurity中存储WebSecurityConfigurerAdapter的LinkedHashMap
		     //调用所有配置类的configurer 的 init configure 方法
		     //
			securityFilterChains.add(securityFilterChainBuilder.build());
		}
		//通过FilterChainProxy对securityFilterChains进行包装
		FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
		if (httpFirewall != null) {
			filterChainProxy.setFirewall(httpFirewall);
		}
		filterChainProxy.afterPropertiesSet();
		
		Filter result = filterChainProxy;
		postBuildAction.run();
		return result;
	}
}

上面代码通过CsrfConfigurer、ExceptionHandlingConfigurer、HeadersConfigurer、SessionManagementConfigurer、SecurityContextConfigurer、RequestCacheConfigurer、AnonymousConfigurer 、ServletApiConfigurer、DefaultLoginPageConfigurer、LogoutConfigurer 等对象的 configure 方法 添加过滤器,我们配置对应的Configurer对象就能修改过滤器要拦截的内容,过滤器如下

WebAsyncManagerIntegrationFilter

SecurityContextPersistenceFilter

HeaderWriterFilter

CsrfFilter

LogoutFilter

MyTokenFilter

UsernamePasswordAuthenticationFilter

DefaultLoginPageGeneratingFilter

DefaultLogoutPageGeneratingFilter

RequestCacheAwareFilter

SecurityContextHolderAwareRequestFilter

AnonymousAuthenticationFilter

SessionManagementFilter

ExceptionTranslationFilter

FilterSecurityInterceptor

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值