一、过滤器
Spring Security 的 Servlet 支持基于 Servlet 过滤器,因此首先了解过滤器的作用会很有帮助。
下图为单个 HTTP 请求的处理程序的典型分层。

客户端向应用程序发送一个请求,运行容器创建一个FilterChain(过滤链),其中包括所有的Filter实例和Servlet。过滤器根据URI路径处理请求和响应。
在一个SpringMvc(Spring Boot)应用程序中,一般只有一个Servlet实例,也就是 DispatcherServlet,他们按照指定的顺序(每个Filter实例实例的顺序非常重要),共同协作。
一个简单的自定义过滤器代码示例:
// 使用@ServletComponentScan添加在启动类上扫描该自定义过滤器
@WebFilter(filterName = "simpleFilter", urlPatterns = {"/*"})
@Slf4j
public class SimpleFilter3 implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
log.info("初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("业务处理开始");
filterChain.doFilter(servletRequest, servletResponse);
log.info("业务处理结束");
}
public void destroy() {
log.info("销毁");
}
}
二、DelegatingFilterProxy
Spring提供了一个名为DelegatingFilterProxy的实现,它允许Servlet容器和Spring IoC容器的生命周期之间进行桥接。
Servlet容器使用自己的标准注册Filter实例,但它不知道Spring IoC容器中定义的过滤器Bean。在有了DelegatingFilterProxy后就可以很方便的在Servlet中使用Spring IoC容器来管理过滤器Bean。
在请求响应过程中,DelegatingFilterProxy从Spring IoC容器中查询注册的过滤器Bean对象,然后调用Bean的过滤方法。
下图为DelegatingFilterProxy是如何让使用Filter实例和FilterChain的。

从DelegatingFilterProxy源码中可以看到该类包含了Spring IoC容器和被代理的过滤器:

一个简单的DelegatingFilterProxy使用代码示例:
// Spring定义的Bean Filter
@Component("simpleFilter")
@Slf4j
public class SimpleFilter2 implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
log.info("初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("业务处理开始");
filterChain.doFilter(servletRequest, servletResponse);
log.info("业务处理结束");
}
public void destroy() {
log.info("销毁");
}
}
@Configuration
public class SimpleConfig {
@Bean
public DelegatingFilterProxyRegistrationBean delegatingFilterProxyRegistrationBean() {
DelegatingFilterProxyRegistrationBean delegatingFilterProxy = new DelegatingFilterProxyRegistrationBean("simpleFilter");
delegatingFilterProxy.addUrlPatterns("/*");
delegatingFilterProxy.setOrder(-5);
Map<String, String> initParameters = new HashMap<>();
initParameters.put("targetFilterLifecycle", "true");
delegatingFilterProxy.setInitParameters(initParameters);
return delegatingFilterProxy;
}
}
三、FilterChainProxy
Spring Security提供FilterChainProxy代理类,是Spring Security使用的核心,用于代理Spring Security中所有的SecurityFilterChain,而在SecurityFilterChain 中又包含多个Spring Security声明的Filter
下图FilterChainProxy在整个请求响应过程中的作用。

从FilterChainProxy源码中可以看到该类代理了Spring Security中所有的SecurityFilterChain:

FilterChainProxy本质上是一个特殊的过滤器,通过DelegatingFilterProxy进行代理,所有其也是一个Bean对象。
在SecurityFilterChain过滤链中通常都是Bean对象,通过FilterChainProxy进行注册与直接通过Servlet容器或通过DelegatingFilterProxy进行注册相比,FilterChainProxy注册有很多优势:
- 它为
Spring Security的所有Servlet支持提供了一个起点,如果需要对Spring Security的Servlet支持进行故障诊断可以在在FilterchainProxy中添加一个调试点。 - 可以执行一些不被视为可有可无的任务,例如,清除了
SecurityContext以避免内存泄漏、应用Spring Security的HttpFirewall来保护应用程序免受某些类型的攻击 - 在确定何时应该调用
SecurityFilterChain方面提供了更大的灵活性,在Servlet容器中,Filter实例仅基于URL被调用。FilterChainProxy可以通过使用RequestMatcher接口,根据HttpServletRequest中的任何内容确定调用。


















