首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Springserver.Forward头.策略本机vs框架

Springserver.Forward头.策略本机vs框架
EN

Stack Overflow用户
提问于 2021-07-09 14:15:30
回答 1查看 14.4K关注 0票数 20

最近,我将spring引导从1.x升级到2.y,并面临这样的问题,即使用http方案而不是https生成仇恨链接。

后来,我发现使用spring 2.2+时,必须使用以下属性

代码语言:javascript
运行
复制
server.forward-headers-strategy=NATIVE

其中可以有NATIVEFRAMEWORKNONE之一。

NONE属性非常直接,它完全禁止使用前向标头。

但是没有关于NATIVEFRAMEWORK的明确文档。我在很多地方都看到过,在大多数情况下,NATIVE的工作效果最好。但是,当我们使用这些属性时,没有解释幕后到底发生了什么。

这里的文件没有提供足够的信息让我在本机/框架之间进行选择。它所显示的只是由谁来处理相应值的转发头。Servlet容器?还是Spring框架?但这又回到了第一步,我应该让集装箱来处理吗?还是框架?我什么时候应该选择一个而不是另一个?

我使用REST web应用程序与外部tomcat和Hateoas来生成链接。

如何决定是使用NATIVE还是FRAMEWORK属性?什么时候一个比另一个更好?为什么?

我的春季版:2.4.6

我已经尝试过的引用:

编辑:

我尝试了这两种解决方案,framework为我工作,但在外部tomcat环境中不使用native。我用嵌入式tomcat创建了一个新的spring引导web应用程序,nativeframework都能工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-07-09 15:03:25

框架

FRAMEWORK使用Spring的支持来处理转发的头文件。例如,Spring在ForwardedHeaderFilter时为Spring创建了一个server.forward-headers-strategy=framework bean。

代码语言:javascript
运行
复制
@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自动配置的嵌入式Tomcat处理非标准标头X-Forwarded-HostX-Forwarded-PortX-Forwarded-ProtoX-Forwarded-Ssl,而不是X-Forwarded-Prefix

X-转发前缀

例如,API网关运行在localhost:8080上,api服务sga-booking运行在localhost:20000上。将API网关路由/sga-booking转发给api服务sga-booking。对localhost:8080/sga-booking的请求包含标题:

代码语言:javascript
运行
复制
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自动配置的嵌入式Tomcat

使用属性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,以处理转发的标头。请注意,没有处理X-Forwarded-Prefix

代码语言:javascript
运行
复制
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处理转发的头,比如Spring配置什么,我认为应该通过添加配置RemoteIpValve

代码语言:javascript
运行
复制
<Context>
  ...
  <Valve className="org.apache.catalina.valves.RemoteIpValve" 
         hostHeader="X-Forwarded-Host"
         portHeader="X-Forwarded-Port"
       ...
  />
  ...
</Context>

给Tomcat server.xml?还是context.xml?查找所有远程ip阀门属性这里。注意,没有任何属性与X-Forwarded-Prefix相关。

Tomcat滤波器RemoteIpFilter可能具有类似的功能。我不知道他们的区别。

参考文献

票数 23
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68318269

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档