前言
本文是对 Spring Security Core 4.0.4 Release 进行源码分析的系列文章之一;
本系列开始,将讲解有关 Spring Security 的配置相关的内容;
本文为作者的原创作品,转载需注明出处;
简介
由前面的文章分析可知 DelegatingFilterProxy 是 Web Servlet Filters 中的一个 Filter;该 Filter 代理了 FilterChainProxy;FilterChainProxy 又包含了多个 SecurityFilterChain 对象;由此,整个 Spring Security 的过滤链的机制由此就建立起来了;但是问题来了,DelegatingFilterProxy 本身作为 Filter 是如何注册到 Spring Web 容器中的呢?本文,笔者将会带领读者们来回答这个问题;
笔者使用的环境是 Spring Boot,该加载的方式与 Spring MVC 的方式有很大的异同;Spring MVC 的加载方式可以参考 http://www.tianshouzhi.com/api/tutorials/spring_security_4/262 章节“过滤器注册过程的源码分析”部分,该部分详细的介绍了如何通过 ServletContainerInitializer 来初始化并加载过滤器 Filters;
DelegatingFilterProxy 载入流程分析
DelegatingFilterProxyRegistrationBean
本小节将记录笔者为了搞清楚在 Spring Boot 环境下 DelegatingFilterProxy 是如何作为 Filter 加载入 Spring Web 容器中的;
首先,将断点打在 DelegatingFilterProxy(String targetBeanName, WebApplicationContext wac) 中,我们将会得到如下的调试状态,
如图所示,Spring Boot 使用的是 TomcatEmbeddedContext 的方式来加载的 Filters,所以和 Spring MVC 通过使用 AbstractSecurityWebApplicationInitializer 来加载 Filter 的方式不同,下面我们就这种方式来进行分析,看看是如何通过 TomcatEmbeddedContext 一步一步的来加载 Filters 的?
然后,看 AnnotationConfigEmbeddedWebApplicationContext.setInitialize(ServletContext) 方法
答案就在 getServletContextInitializerBeans() 方法中,该方法返回如下对象列表;
是的,我发现了什么,似曾相似,这不就是前文提到的 6 大 Filters;而DelegatingFilterProxyRegistrationBean
所代表的正是DelegatingFilterProxy
;下面深入 getServletContextInitializerBeans() 方法,
上面的代码非常的关键了,通过传入 BeanFactory 作为构造参数来初始化构造 ServletContextInitializerBeans 的来获得这 6 大 Filters; 这里需要注意的一个细节是,ServletContextInitializerBeans 本身是一个 Collection 类型;
addServletContextInitializerBeans(ListableBeanFactory beanFactory)
可见构造函数中首先通过 addServletContextInitializerBeans(ListableBeanFactory beanFactory),然后通过在 Spring 容器中通过获取类型为 ServletContextInitializer 的 Spring Beans,DelegatingFilterProxyRegistrationBean
和其余 5 大 Filters 均实现了该接口;所以,DelegatingFilterProxyRegistrationBean 以及其余 Filters 将会在这里被取出;addServletContextInitializerBean(String beanName, ServletContextInitializer initializer, ListableBeanFactory beanFactory)
该方法将对应的 Filter 加入 initializers 中,既是将 Filter 注入到 Spring Web 容器中;
从上述的第 #1 点可以知道,通过从容器中查找类型为 ServletContextInitializer 的 bean,既可以找到 DelegatingFilterProxyRegistrationBean 和其余 5 大 Filters;那么问题是,这些 Filters 是如何提前被注入到 Spring 容器中的呢?
RegistrationBean
本小节将回答上一小节末尾所提到的问题,那就是DelegatingFilterProxyRegistrationBean
是如何作为 Filter 注入到 Spring 容器中的?其实,它的答案正是 org.springframework.boot.context.embedded.RegistrationBean 所涉及到的逻辑,该部分逻辑也正是 Spring Boot 的专属逻辑;下面,笔者将简要介绍一下DelegatingFilterProxyRegistrationBean
做为 Filter 被注入到 Spring 容器中的逻辑,看一下 org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration 类的逻辑
通过 SecurityFilterAutoConfiguration 自动的将DelegatingFilterProxyRegistrationBean
注入到 Spring Web 容器中;Spring Boot 放弃了以往类似 Spring MVC 加载 Filter 繁琐的方式,直接通过 RegisterBean 的方式来注册 ServletContext 中所需要的资源;这里不打算细说有关 RegistrationBean 的相关的逻辑,将来打算将这部分内容在 Spring Boot 的相关章节中做进一步描述;
Reference: http://www.tianshouzhi.com/api/tutorials/springboot/89
FilterChainProxy 作为代理载入 DelegatingFilterProxy 的流程
这里不打算做深入的分析了,下面描述了该载入流程的入口方法,
DelegatingFilterProxy.class
1 | /** |
核心逻辑在上述代码的第 16 行;target name 既是 “springSecurityFilterChain”,而该 bean name 对应的正好是 FilterChainProxy Spring Bean;