Spring Security 源码分析九:Java config - 加载 DelegatingFilterProxy

栏目: 后端 · 发布时间: 6年前

内容简介:本文是对 Spring Security Core 4.0.4 Release 进行源码分析的系列文章之一;本系列开始,将讲解有关 Spring Security 的配置相关的内容;本文为作者的原创作品,转载需注明出处;

本文是对 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 Security 源码分析九:Java config - 加载 DelegatingFilterProxy

如图所示,Spring Boot 使用的是 TomcatEmbeddedContext 的方式来加载的 Filters,所以和 Spring MVC 通过使用 AbstractSecurityWebApplicationInitializer 来加载 Filter 的方式不同,下面我们就这种方式来进行分析,看看是如何通过 TomcatEmbeddedContext 一步一步的来加载 Filters 的?

然后,看 AnnotationConfigEmbeddedWebApplicationContext.setInitialize(ServletContext) 方法

Spring Security 源码分析九:Java config - 加载 DelegatingFilterProxy

答案就在 getServletContextInitializerBeans() 方法中,该方法返回如下对象列表;

Spring Security 源码分析九:Java config - 加载 DelegatingFilterProxy

是的,我发现了什么,似曾相似,这不就是前文提到的6 大 Filters;而 DelegatingFilterProxyRegistrationBean 所代表的正是 DelegatingFilterProxy ;下面深入 getServletContextInitializerBeans() 方法,

Spring Security 源码分析九:Java config - 加载 DelegatingFilterProxy

上面的代码非常的关键了,通过传入 BeanFactory 作为构造参数来初始化构造 ServletContextInitializerBeans 的来获得这 6 大 Filters; 这里需要注意的一个细节是,ServletContextInitializerBeans 本身是一个 Collection 类型;

Spring Security 源码分析九:Java config - 加载 DelegatingFilterProxy
  1. addServletContextInitializerBeans(ListableBeanFactory beanFactory)

    可见构造函数中首先通过 addServletContextInitializerBeans(ListableBeanFactory beanFactory),然后通过在 Spring 容器中通过获取类型为 ServletContextInitializer 的 Spring Beans, DelegatingFilterProxyRegistrationBean 和其余 5 大 Filters 均实现了该接口;所以,DelegatingFilterProxyRegistrationBean 以及其余 Filters 将会在这里被取出;

  2. 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 类的逻辑

Spring Security 源码分析九:Java config - 加载 DelegatingFilterProxy

通过 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

/**
 * Initialize the Filter delegate, defined as bean the given Spring
 * application context.
 * <p>The default implementation fetches the bean from the application context
 * and calls the standard {@code Filter.init} method on it, passing
 * in the FilterConfig of this Filter proxy.
 * @param wac the root application context
 * @return the initialized delegate Filter
 * @throws ServletException if thrown by the Filter
 * @see #getTargetBeanName()
 * @see #isTargetFilterLifecycle()
 * @see #getFilterConfig()
 * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
 */
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
   Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
   if (isTargetFilterLifecycle()) {
      delegate.init(getFilterConfig());
   }
   return delegate;
}

核心逻辑在上述代码的第 16 行;target name 既是 “springSecurityFilterChain”,而该 bean name 对应的正好是 FilterChainProxy Spring Bean;


以上所述就是小编给大家介绍的《Spring Security 源码分析九:Java config - 加载 DelegatingFilterProxy》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Visual Thinking

Visual Thinking

Colin Ware / Morgan Kaufmann / 2008-4-18 / USD 49.95

Increasingly, designers need to present information in ways that aid their audiences thinking process. Fortunately, results from the relatively new science of human visual perception provide valuable ......一起来看看 《Visual Thinking》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具