Spring Boot 和Spring Security

本文是描述Spring Boot 与Spring Security在web环境下相关的学习笔记,偏向于原理性质。

在Spring Boot下,它其中包含了security的自动配置是  SecurityAutoConfiguration和SecurityFilterAutoConfiguration

要使用Spring Securty,就会使用注解EnableWebSecurity 来开启安全控制,从这个注解的源码中,可以看到它import 了 WebSecurityConfiguration

Spring Security的入口过滤器是如何放入web容器的?

Spring Security是依赖Filter,而它的入口Filter是在SecurityFilterAutoConfiguration中使用DelegatingFilterProxyRegistrationBean 将

DelegatingFilterProxy 过滤器放入到web容器中并命名为springSecurityFilterChain

根据DelegatingFilterProxy的原理,那肯定存在一个springSecurityFilterChain的bean,这个bean是在WebSecurityConfiguration中定义注入的。 

	@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public Filter springSecurityFilterChain() throws Exception {
		boolean hasConfigurers = webSecurityConfigurers != null
				&& !webSecurityConfigurers.isEmpty();
		if (!hasConfigurers) {
			WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
					.postProcess(new WebSecurityConfigurerAdapter() {
					});
			webSecurity.apply(adapter);
		}
		return webSecurity.build();  //1
	}

Spring Security的系列过滤器是怎么加上的?

入口点实际是上面代码的 webSecurity.build() ,经过层层查看代码,可以看到最终调用的了一个init方法,即:org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#init

	public void init(final WebSecurity web) throws Exception {
		final HttpSecurity http = getHttp();
		web.addSecurityFilterChainBuilder(http).postBuildAction(new Runnable() {
			public void run() {
				FilterSecurityInterceptor securityInterceptor = http
						.getSharedObject(FilterSecurityInterceptor.class);
				web.securityInterceptor(securityInterceptor);
			}
		});
	}

进入getHttp方法中,我们可以看到如下一段代码(仅截取了一部分):

		if (!disableDefaults) {
			// @formatter:off
			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();
			// @formatter:on

到这里就比较清晰了,它的这些默认加载的过滤器实际上是在这里配置的,并且这里还包含一个配置参数来控制disableDefaults

默认值为false。

对于刚接触的朋友们,我们可能有一个疑问:这不是调用了些方法吗,这与过滤器有什么关系呢? 带着疑问我们接着往下看

我们可以进入一个方法来具体看看,比如 csrf ,它返回的是CsrfConfigurer 也就是说它使用了该配置器,

然后进入CsrfConfigurer类的configure 方法,就可以看到它是使用了CsrfFilter 过滤器。

     
	@Override
	public void configure(H http) throws Exception {

		CsrfFilter filter = new CsrfFilter(this.csrfTokenRepository);


		RequestMatcher requireCsrfProtectionMatcher = getRequireCsrfProtectionMatcher();
		if (requireCsrfProtectionMatcher != null) {
			filter.setRequireCsrfProtectionMatcher(requireCsrfProtectionMatcher);
		}
		AccessDeniedHandler accessDeniedHandler = createAccessDeniedHandler(http);
		if (accessDeniedHandler != null) {
			filter.setAccessDeniedHandler(accessDeniedHandler);
		}
		LogoutConfigurer<H> logoutConfigurer = http.getConfigurer(LogoutConfigurer.class);
		if (logoutConfigurer != null) {
			logoutConfigurer
					.addLogoutHandler(new CsrfLogoutHandler(this.csrfTokenRepository));
		}
		SessionManagementConfigurer<H> sessionConfigurer = http
				.getConfigurer(SessionManagementConfigurer.class);
		if (sessionConfigurer != null) {
			sessionConfigurer.addSessionAuthenticationStrategy(
					new CsrfAuthenticationStrategy(this.csrfTokenRepository));
		}
		filter = postProcess(filter);
		http.addFilter(filter);
	}

参考资料:

https://www.jianshu.com/p/d5ce890c67f7

https://www.jianshu.com/p/e21c436543af

https://blog.csdn.net/qq_35494808/article/details/81537415

https://blog.csdn.net/liushangzaibeijing/article/details/81220610

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值