Spring Boot 和Spring Security

    xiaoxiao2022-07-03  114

    本文是描述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)