|
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.7! |
过滤器
表单数据
浏览器只能通过 HTTP GET 或 HTTP POST 提交表单数据,但非浏览器客户端也可以
使用 HTTP PUT、PATCH 和 DELETE。Servlet API 需要ServletRequest.getParameter*()方法仅支持 HTTP POST 的表单字段访问。
这spring-webmodule 提供FormContentFilter拦截 HTTP PUT、PATCH 和 DELETE
内容类型为application/x-www-form-urlencoded中,从
请求正文,并将ServletRequest创建表单数据
可通过ServletRequest.getParameter*()方法系列。
请求头转发
当请求通过负载均衡器等代理时,主机、端口和 方案可能会更改,这使得创建指向正确 Host、Port 和 Scheme。
RFC 7239 定义了ForwardedHTTP 标头
代理可用于提供有关原始请求的信息。
非标准标头
还有其他非标准标头,包括X-Forwarded-Host,X-Forwarded-Port,X-Forwarded-Proto,X-Forwarded-Ssl和X-Forwarded-Prefix.
X-转发主机
虽然不是标准的,X-Forwarded-Host: <host>是事实上的标准标头,用于将原始主机传送到
downstream server 的例如,如果example.com/resource将发送到
一个代理,它将请求转发到localhost:8080/resource,则X-Forwarded-Host: example.com可以发送通知服务器原始主机是example.com.
X 转发端口
虽然不是标准的,X-Forwarded-Port: <port>是事实上的标准标头,用于
将原始端口传送到下游服务器。例如,如果example.com/resource将发送到代理,该代理将请求转发到localhost:8080/resource,则X-Forwarded-Port: 443可以发送
通知服务器原始端口为443.
X 转发原型
虽然不是标准的,X-Forwarded-Proto: (https|http)是用于通信原始协议(例如 HTTPS / HTTPS)的事实标准标头
到下游服务器。例如,如果example.com/resource将发送到
一个代理,它将请求转发到localhost:8080/resource,则X-Forwarded-Proto: https可以发送通知服务器原来的协议是https.
X-转发 SSL
虽然不是标准的,X-Forwarded-Ssl: (on|off)是事实上的标准标头,用于传达
原始协议(例如 HTTPS / HTTPS)到下游服务器。例如,如果example.com/resource将发送到代理,该代理将请求转发到localhost:8080/resource,则X-Forwarded-Ssl: on通知服务器
最初的协议是https.
X 转发前缀
虽然不是标准的,X-Forwarded-Prefix: <prefix>是事实上的标准标头,用于将原始 URL 路径前缀传达给
downstream server 的
用途X-Forwarded-Prefix可能因部署方案而异,并且需要灵活地
允许替换、删除或预置目标服务器的路径前缀。
场景 1:覆盖路径前缀
https://example.com/api/{path} -> http://localhost:8080/app1/{path}
前缀是 capture 组之前的路径的开头{path}.对于代理,
前缀为/api而对于服务器,前缀为/app1.在这种情况下,代理
可以发送X-Forwarded-Prefix: /api具有原始前缀/api覆盖
服务器前缀/app1.
方案 2:删除路径前缀
有时,应用程序可能希望删除前缀。例如,考虑 以下代理到服务器的映射:
https://app1.example.com/{path} -> http://localhost:8080/app1/{path}
https://app2.example.com/{path} -> http://localhost:8080/app2/{path}
代理没有前缀,而应用程序app1和app2具有路径前缀/app1和/app2分别。代理可以发送X-Forwarded-Prefix: 自
让空前缀覆盖服务器前缀/app1和/app2.
|
此部署方案的一个常见情况是许可证按 production application server 部署多个应用程序,并且最好为每个 server 来降低费用。另一个原因是在同一台服务器上运行更多应用程序 order 共享服务器运行所需的资源。 在这些情况下,应用程序需要一个非空的上下文根,因为有多个 应用程序。但是,这在 公共 API,应用程序可以在其中使用不同的子域,从而提供优势 如:
|
方案 3:插入路径前缀
在其他情况下,可能需要在前面加上前缀。例如,考虑 以下代理到服务器的映射:
https://example.com/api/app1/{path} -> http://localhost:8080/app1/{path}
在这种情况下,代理的前缀为/api/app1服务器具有前缀/app1.代理可以发送X-Forwarded-Prefix: /api/app1具有原始前缀/api/app1覆盖服务器前缀/app1.
转发标头过滤器
ForwardedHeaderFilter是一个 Servlet 过滤器,它修改请求以便
a) 根据Forwarded标头,以及 b) 删除这些
标头以消除进一步的影响。过滤器依赖于包装请求,并且
因此,它必须优先于其他过滤器排序,例如RequestContextFilter那
应该使用修改后的请求,而不是原始请求。
安全注意事项
转发的 Headers 存在安全注意事项,因为应用程序无法知道
标头是由代理按预期添加的,还是由恶意客户端添加的。这就是为什么
应将信任边界的代理配置为删除 UntrustedForwarded来自外部的标头。您还可以配置ForwardedHeaderFilter跟removeOnly=true,在这种情况下,它会删除但不使用标头。
调度程序类型
为了支持异步请求和错误调度,此
filter 应该映射为DispatcherType.ASYNC以及DispatcherType.ERROR.
如果使用 Spring Framework 的AbstractAnnotationConfigDispatcherServletInitializer(请参见 Servlet 配置)所有过滤器都自动注册到所有分派
类型。但是,如果通过web.xml或在 Spring Boot 中通过FilterRegistrationBean请务必包括DispatcherType.ASYNC和DispatcherType.ERROR除了DispatcherType.REQUEST.
浅层 ETag
这ShallowEtagHeaderFilterfilter 通过缓存内容来创建 “浅层” ETag
写入响应并从中计算 MD5 哈希。下次客户端发送时,
它执行相同的作,但它也会将计算的值与If-None-Matchrequest 标头,如果两者相等,则返回 304 (NOT_MODIFIED)。
此策略可节省网络带宽,但不节省 CPU,因为必须为每个请求计算完整响应。
状态更改 HTTP 方法和其他 HTTP 条件请求标头,例如If-Match和If-Unmodified-Since不在此筛选器的范围内。控制器级别的其他策略
可以避免计算,并对 HTTP 条件请求提供更广泛的支持。
请参阅 HTTP 缓存。
此过滤器具有writeWeakETag参数,该参数将过滤器配置为写入弱 ETag
类似于以下内容:W/"02a2d595e6ed9a0b24f027f2b63b134d6"(如 RFC 7232 第 2.3 节中所定义)。
为了支持异步请求,必须映射此过滤器
跟DispatcherType.ASYNC以便过滤器可以延迟并成功生成
ETag 添加到最后一个异步调度的末尾。如果使用 Spring Framework 的AbstractAnnotationConfigDispatcherServletInitializer(请参阅 Servlet 配置)
所有过滤器都会自动为所有 Dispatch 类型注册。但是,如果注册
通过web.xml或在 Spring Boot 中通过FilterRegistrationBean请务必包括DispatcherType.ASYNC.
CORS
Spring MVC 通过
控制器。但是,当与 Spring Security 一起使用时,我们建议依赖内置的CorsFilter必须在 Spring Security 的过滤器链之前订购。