簡體   English   中英

Spring server.forward-headers-strategy NATIVE vs FRAMEWORK

[英]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

可以有NATIVEFRAMEWORKNONE

NONE屬性非常簡單,它完全禁止使用前向標頭。

但是沒有關於NATIVEFRAMEWORK明確文檔。 我在很多地方都看到有人提到NATIVE在大多數情況下效果最好。 但是當我們使用這些屬性時,幕后到底發生了什么,並沒有解釋。

此處文檔沒有提供足夠的信息讓我在 Native/Framework 之間進行選擇。 它所說的只是誰處理相應值的轉發標頭。 Servlet 容器? 還是Spring框架? 但它又回到了第 1 方格。我應該讓容器處理它嗎? 還是框架? 什么時候我應該更喜歡一個?

我正在使用帶有外部 tomcat 和Hateoas REST Web 應用程序來生成鏈接。

我如何決定是使用NATIVE還是FRAMEWORK屬性? 什么時候應該優先選擇另一個,為什么?

我的springboot版本: 2.4.6

我已經嘗試過的參考資料:

編輯:

我嘗試了對我有用的解決方案和framework ,但在外部 tomcat 環境中不是native 我創建了一個帶有嵌入式 tomcat 的新 Spring Boot Web 應用程序,並且nativeframework可以工作。

框架

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-HostX-Forwarded-PortX-Forwarded-ProtoX-Forwarded-SslX-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

X 轉發前綴

例如,API 網關在localhost:8080上運行,而 api service sga-bookinglocalhost: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開頭。

Spring Boot 自動配置的嵌入式 Tomcat

使用屬性server.forward-headers-strategy=native ,方法org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer#customizeRemoteIpValve使用屬性server.tomcat.remoteiporg.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信息可能有誤。
為了讓外部 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM