回顾一下 Filter 过滤器
Spring Security的Servlet支持基于Servlet过滤器。
下图显示了单个HTTP请求处理程序的典型分层。
客户端向应用程序发送请求,容器创建一个FilterChain,其中包含 Filters 和Servlet,这些 Filters 和 Servlet 应根据请求URI的路径处理 HttpServletRequest。在Spring MVC应用程序中,Servlet 是 DispatcherServlet 的实例。最多一个 Servlet 可以处理单个 HttpServletRequest 和 HttpServletResponse 。但是,可以使用多个过滤器来:
-
防止调用下游 Filters 或 Servlet。在这种情况下,过滤器通常会写入 HttpServletResponse
-
修改下游 Filters 和 Servlet 使用的 HttpServletRequest 或 HttpServletResponse
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// do something before the rest of the application
chain.doFilter(request, response); // invoke the rest of the application
// do something after the rest of the application
}
由于 Filters 只影响下游 Filters 和 Servlet ,因此每个 Filter 的调用顺序非常重要。
DelegatingFilterProxy
Spring提供了一个名为 DelegatingFilterProxy
的过滤器实现,它允许在 Servlet 容器的生命周期和 Spring 的 ApplicationContext 之间连接。 Servlet 容器允许使用自己的标准注册 Filters ,但它不知道 Spring bean 的定义。 DelegatingFilterProxy
可以通过标准的 Servlet 容器注册机制,将所有工作委托给实现过滤器的 Spring Bean 。
下面是 DelegatingFilterProxy
如何融入过滤器和过滤链的图片。
DelegatingFilterProxy
从 ApplicationContext 中查找 Bean Filter0 ,然后调用 Bean Filter0 。
大白话就是:他的任务就是把持有的 bean 从容器中拿出来。
DelegatingFilterProxy的伪代码如下所示。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// Lazily get Filter that was registered as a Spring Bean
// For the example in DelegatingFilterProxy
delegate
is an instance of Bean Filter0
Filter delegate = getFilterBean(someBeanName);
// delegate work to the Spring Bean
delegate.doFilter(request, response);
}
DelegatingFilterProxy
的另一个好处是,它允许延迟查找 Filter bean 实例。这一点很重要,因为容器需要在启动之前注册 Filter 实例。然而, Spring 通常使用 ContextLoaderListener
来加载 SpringBean ,直到需要注册 Filter 实例之后才能进行加载。
而注入到 servletContext 的方式是通过 DelegatingFilterProxyRegistrationBean
来完成,这个类的主要目的是为了包装 DelegatingFilterProxy
类,并且实现自动注入到 servletContext 的流程
而 DelegatingFilterProxy
可以获取到 FilterChainProxy
这个bean,而这个 bean 注册 SecurityFilterChain
和其中的安全过滤器。
最后使用 SecurityFilterChain
来确定当前请求应该调用哪些 Security Filter
所以 DelegatingFilterProxyRegistrationBean
就是为了将 SecurityFilterChain
加入servlet容器中。
而 DelegatingFilterProxy
就是持有 SecurityFilterChain
的 bean 名称的一个 Filter 。
<