spring-web 模块提供了一些有用的过滤器:

  • Form Data / 表单数据
  • Forwarded Headers / 转发头
  • Shallow ETag
  • CORS / 跨域

Form Data

浏览器只能通过 HTTP GET 或 HTTP POST 提交表单数据,但非浏览器客户端也可以使用 HTTP PUT、PATCH 和 DELETE。Servlet API 要求ServletRequest.getParameter*()方法只支持 HTTP POST 的表单字段访问。

spring-web 模块提供了 FormContentFilter 来拦截内容类型为 application/x-www-form-urlencoded的 HTTP PUT、PATCH 和 DELETE 请求,从请求正文中读取表单数据,并包装 ServletRequest,使表单数据通过 ServletRequest.getParameter*() 系列方法可用。

Forwarded Headers

当请求通过代理(如负载均衡器)时,主机、端口和方案可能会发生变化,这使得从客户端角度创建指向正确主机、端口和方案的链接成为一种挑战。

RFC 7239 定义了转发的 HTTP 头,代理可以用它来提供关于原始请求的信息。还有其他非标准的头,包括 X-Forwarded-Host、X-Forwarded-Port、X-Forwarded-Proto、X-Forwarded-SSL 和 X-Forwarded-Prefix。

ForwardedHeaderFilter 是一个 Servlet 过滤器,它对请求进行修改,以便:

  1. 根据 Forwarded 头信息改变主机、端口和方案
  2. 删除这些头信息以消除进一步的影响

这个过滤器依赖于对请求的包装,因此它必须排在其他过滤器的前面,比如 RequestContextFilter,它应该对修改后的请求而不是原始请求起作用。

对于转发的头信息有安全方面的考虑,因为应用程序无法知道头信息是由代理添加的,还是由恶意的客户端添加的。这就是为什么在信任边界的代理应该被配置为删除来自外部的不被信任的转发头信息。你也可以将 ForwardedHeaderFilter 配置为 removeOnly=true,在这种情况下,它将删除但不使用这些头信息。

为了支持 异步请求 和错误派发,这个过滤器应该与 DispatcherType.ASYNCDispatcherType.ERROR进行映射。如果使用 Spring 框架的AbstractAnnotationConfigDispatcherServletInitializer(见 Servlet 配置),所有过滤器都会自动注册为所有的派发类型。然而,如果通过 web.xml或在 Spring Boot 中通过 FilterRegistrationBean 注册过滤器,请确保除了 DispatcherType.ASYNCDispatcherType.ERROR之外,还要包括 DispatcherType.REQUEST

Shallow ETag

ShallowEtagHeaderFilter 通过缓存写入响应的内容并计算出一个 MD5 哈希值来创建一个 「Shallow」 ETag。客户端下次发送时,它做同样的事情,但它也将计算的值与 If-None-Match请求头进行比较,如果两者相等,则返回 304(NOT_MODIFIED)。

这种策略可以节省网络带宽,但不能节省 CPU,因为必须为每个请求计算完整的响应。前面描述的控制器层面的其他策略,可以避免计算。参见HTTP 缓存

这个过滤器有一个 writeWeakETag参数,配置过滤器写入类似以下的 weak ETag。W/"02a2d595e6ed9a0b24f027f2b63b134d6"如 RFC 7232 第 2.3 节中所定义)。

为了支持 异步请求,这个过滤器必须与 DispatcherType.ASYNC进行映射,这样过滤器就可以延迟并成功地生成 ETag 到最后一个异步调度的结束。如果使用 Spring 框架的 AbstractAnnotationConfigDispatcherServletInitializer(见 Servlet 配置),所有的过滤器都会自动注册为所有调度类型。然而,如果通过 web.xml 或在 Spring Boot 中通过 FilterRegistrationBean 注册过滤器,请确保包括 DispatcherType.ASYNC

CORS / 跨域

Spring MVC 通过控制器上的注解为 CORS 配置提供了细粒度的支持。然而,当与 Spring Security 一起使用时,我们建议依靠内置的 CorsFilter,它必须在 Spring Security 的过滤器链之前排序。

更多细节请参见 CORS CORS 过滤器 部分。