[英]Spring server.forward-headers-strategy NATIVE vs FRAMEWORK
我最近將 spring boot 從 1.x 升級到 2.y 並面臨這個問題,其中 hateoas 鏈接是使用http
方案而不是https
生成的。
后來發現用spring boot 2.2+,強制使用如下屬性
server.forward-headers-strategy=NATIVE
可以有NATIVE
或FRAMEWORK
或NONE
。
NONE
屬性非常簡單,它完全禁止使用前向標頭。
但是沒有關於NATIVE
與FRAMEWORK
明確文檔。 我在很多地方都看到有人提到NATIVE
在大多數情況下效果最好。 但是當我們使用這些屬性時,幕后到底發生了什么,並沒有解釋。
此處的文檔沒有提供足夠的信息讓我在 Native/Framework 之間進行選擇。 它所說的只是誰處理相應值的轉發標頭。 Servlet 容器? 還是Spring框架? 但它又回到了第 1 方格。我應該讓容器處理它嗎? 還是框架? 什么時候我應該更喜歡一個?
我正在使用帶有外部 tomcat 和Hateoas
REST Web 應用程序來生成鏈接。
我如何決定是使用NATIVE
還是FRAMEWORK
屬性? 什么時候應該優先選擇另一個,為什么?
我的springboot版本: 2.4.6
我已經嘗試過的參考資料:
編輯:
我嘗試了對我有用的解決方案和framework
,但在外部 tomcat 環境中不是native
。 我創建了一個帶有嵌入式 tomcat 的新 Spring Boot Web 應用程序,並且native
和framework
可以工作。
FRAMEWORK
使用 Spring 的支持來處理轉發的標頭。 例如,當server.forward-headers-strategy=framework
時,Spring Boot 會自動為 Spring MVC 創建一個ForwardedHeaderFilter
bean。
@Bean
@ConditionalOnMissingFilterBean(ForwardedHeaderFilter.class)
@ConditionalOnProperty(value = "server.forward-headers-strategy", havingValue = "framework")
public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
ForwardedHeaderFilter
處理非標准標頭X-Forwarded-Host
、 X-Forwarded-Port
、 X-Forwarded-Proto
、 X-Forwarded-Ssl
和X-Forwarded-Prefix
。
NATIVE
使用底層容器對轉發標頭的本機支持。 底層容器指的是tomcat、jetty、netty等,比如Spring Boot自動配置的內嵌Tomcat處理非標准headers X-Forwarded-Host
, X-Forwarded-Port
, X-Forwarded-Proto
, X-Forwarded-Ssl
,但不是X-Forwarded-Prefix
。
例如,API 網關在localhost:8080
上運行,而 api service sga-booking
在localhost:20000
上運行。 API 網關路由/sga-booking
被轉發到 api 服務sga-booking
。 對localhost:8080/sga-booking
的請求包含標題:
forwarded = proto=http;host="localhost:8080";for="0:0:0:0:0:0:0:1%0:46706"
x-forwarded-for = 0:0:0:0:0:0:0:1%0
x-forwarded-proto = http
x-forwarded-prefix = /sga-booking
x-forwarded-port = 8080
x-forwarded-host = localhost:8080
host = 192.168.31.200:20000
當ForwardedHeaderFilter
處理包括X-Forwarded-Prefix
在內的轉發標頭時,生成的鏈接以localhost:8080/sga-booking
開頭。 如果未處理X-Forwarded-Prefix
,則生成的鏈接以localhost:8080
開頭。
使用屬性server.forward-headers-strategy=native
,方法org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer#customizeRemoteIpValve
使用屬性server.tomcat.remoteip
( org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.Remoteip
配置RemoteIpValve
org.springframework.boot.autoconfigure.web.ServerProperties.Tomcat.Remoteip
) 來處理轉發的標頭。 請注意,不處理X-Forwarded-Prefix
。
private void customizeRemoteIpValve(ConfigurableTomcatWebServerFactory factory) {
Remoteip remoteIpProperties = this.serverProperties.getTomcat().getRemoteip();
String protocolHeader = remoteIpProperties.getProtocolHeader();
String remoteIpHeader = remoteIpProperties.getRemoteIpHeader();
if (StringUtils.hasText(protocolHeader) || StringUtils.hasText(remoteIpHeader)
|| getOrDeduceUseForwardHeaders()) {
RemoteIpValve valve = new RemoteIpValve();
valve.setProtocolHeader(StringUtils.hasLength(protocolHeader) ? protocolHeader : "X-Forwarded-Proto");
if (StringUtils.hasLength(remoteIpHeader)) {
valve.setRemoteIpHeader(remoteIpHeader);
}
valve.setInternalProxies(remoteIpProperties.getInternalProxies());
try {
// X-Forwarded-Host by default
valve.setHostHeader(remoteIpProperties.getHostHeader());
}
catch (NoSuchMethodError ex) {
// Avoid failure with war deployments to Tomcat 8.5 before 8.5.44 and
// Tomcat 9 before 9.0.23
}
// X-Forwarded-Port by default
valve.setPortHeader(remoteIpProperties.getPortHeader());
valve.setProtocolHeaderHttpsValue(remoteIpProperties.getProtocolHeaderHttpsValue());
factory.addEngineValves(valve);
}
}
// 抱歉,我畢業后好多年沒有玩過香草 Tomcat。 以下Tomcat信息可能有誤。
為了讓外部 Tomcat 處理轉發的 headers,就像 Spring Boot 配置的那樣,我認為應該通過 add 配置一個RemoteIpValve
<Context>
...
<Valve className="org.apache.catalina.valves.RemoteIpValve"
hostHeader="X-Forwarded-Host"
portHeader="X-Forwarded-Port"
...
/>
...
</Context>
到 Tomcat server.xml
? 或context.xml
? 在此處查找所有遠程 ip Valve 屬性。 請注意,沒有任何屬性與X-Forwarded-Prefix
。
Tomcat 過濾器RemoteIpFilter
可能有類似的功能。 我不知道他們的區別。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.