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

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

内容简介:本文是对 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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

嗨翻C语言

嗨翻C语言

[美]David Griffiths、[美]Dawn Griffiths / 程亦超 / 人民邮电出版社 / 2013-9 / 99.00

你能从这本书中学到什么? 你有没有想过可以轻松学习C语言?《嗨翻C语言》将会带给你一次这样的全新学习 体验。本书贯以有趣的故事情节、生动形象的图片,以及不拘一格、丰富多样的练 习和测试,时刻激励、吸引、启发你在解决问题的同时获取新的知识。你将在快乐 的气氛中学习语言基础、指针和指针运算、动态存储器管理等核心主题,以及多线 程和网络编程这些高级主题。在掌握语言的基本知识......一起来看看 《嗨翻C语言》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

MD5 加密
MD5 加密

MD5 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具