Spring Security 源码分析六:Spring Security 在容器中初始化过程二

前言

本文是对 Spring Security Core 4.0.4 Release 进行源码分析的系列文章之一;

Spring Security 在 Spring 容器中的初始化过程分为两个部分,首先,第一个部分,解析配置,生成对应的 Bean Definitions,并将对应的 Bean Definitions 保存到 Spring 容器中;其次,根据生成的 Bean Definitions 生成对应的 Bean,并同样将其保存到 Spring 容器中;

备注,有关 Bean Definitions 的解析并注册相关源码分析部分参考 Spring Core Container 源码分析七:注册 Bean Definitions,有关对 Bean Definitions 中所注册的 Bean 进行初始化的源码分析部分参考 Spring Core Container 源码分析三:Spring Beans 初始化流程分析

本文是对 Spring Security 初始化过程的第二部分进行的描述;

本文为作者的原创作品,转载需注明出处;

分析思路

本文将使用 Spring Security 源码分析四:Spring MVC 例子 作为调试用例,进行源码分析;

Spring Security 源码分析五:Spring Security 在容器中初始化过程一的分析过程中,通过对上述 demo 中的 Spring Security 的相关配置元素 <http> <authentication-manager> <user-service> 进行解析后生成了众多的 bean definitions,不过,最重要的有 DefaultSecurityFilterChain、AuthenticationManager 以及 AccessDecisionManager 相关的 bean definitions;所以,本文,作者最主要的分析思路是,从这三个 domain object 入手,逐个分析他们的初始化流程;

DefaultSecurityFilterChain

DefaultSecurityFilterChain 的 bean definitions 是在 Spring Security 源码分析五:Spring Security 在容器中初始化过程一的 http 章节的 3.6 步骤中创建的,可以知道,创建过程中,初始化了大量的相关的 filters 的 bean definitions,比如 CsrfFilter、SecurityContextPersistenceFilter、SessionManagementFilters 等等;

所以,在上述 bean definitions 都被初始化并加载入 Spring 容器以后,Spring 容器遍历所有相关的 bean definitions,并根据这些 bean definitions 开始初始化相关的 bean;Spring 容器;相关细节就是,当 Spring 容器在遍历所有的单例的 bean names 的过程中,当 bean name = org.springframework.security.filterChains 的时候,便开始初始化相关的 bean,而 DefaultSecurityFilterChain 正是该 bean name 相关联的一个 bean,那么它将会被 Spring 容器进行初始化;

Spring 容器会根据之前所创建的 DefaultSecurityFilterChain 的 bean definitions 通过反射初始化并得到 DefaultSecurityFilterChain 实例;在初始化得到 DefaultSecurityFilterChain 之前,所有相关的 Filters 也会相应的被创建,相关的 Filters 有,

  • org.springframework.security.web.context.SecurityContextPersistenceFilter,
  • org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter
  • org.springframework.security.web.header.HeaderWriterFilter
  • org.springframework.security.web.csrf.CsrfFilter
  • org.springframework.security.web.authentication.logout.LogoutFilter
  • org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
  • org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
  • org.springframework.security.web.authentication.www.BasicAuthenticationFilter
  • org.springframework.security.web.savedrequest.RequestCacheAwareFilter@2662511e,
  • org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter,
  • org.springframework.security.web.authentication.AnonymousAuthenticationFilter,
  • org.springframework.security.web.session.SessionManagementFilter,
  • org.springframework.security.web.access.ExceptionTranslationFilter,
  • org.springframework.security.web.access.intercept.FilterSecurityInterceptor

上面这些 Filters 就是 Http Security 做到 Web 安全的核心了;

备注:DefaultSecurityFilterChain 是继承自 SecurityFilterChain 的,SecurityFilterChain 是实现 Spring Security 的核心机制,它通过一个 Spring Web Filter 扩展出一系列与 Spring Security 相关的 Filters,这些 Filters 既是上述所描述的所有相关的 Filters;相关核心内容参考下一章节 ;

Authentication Manager

AuthenticationManager 的实现类是 ProviderManager,所以,这里我们就来窥探一下 ProviderManager 在 Spring 容器中是如何被初始化的;初始化 Provider Manager 需要一系列的 Authentication Provider 作为构造参数,不过从我们当前的 demo 的调用过程中,只是用到了 DaoAuthenticationProvider,相关的 bean definition 的创建过程参考 Spring Security 源码分析五:Spring Security 在容器中初始化过程一authentication manager 小节的第 5 步;那么由此可知,当初始化 Provider Manager 实例的时候,是用到的 Authentication Provider 正是 DaoAuthenticationProvider;

AccessDecisionManager

AccessDecisionManager 是确认当前用户是否有访问该资源的权限,那么 AccessDecisonManager 相关的 bean definitions 是在初始化 filters 及其 handlers 相关的 bean definitions 中初始化 FilterSecurityInterceptor 的时候创建的,过程中,会初始化 AffirmativeBased 的 bean definition 作为 AccessDecisionManager;所以,在 Spring 容器初始化相关的 AccessDecisionManager 的时候,初始化的是 AffirmativeBased;