繁体   English   中英

带有嵌入式 Tomcat 的 Spring Boot 应用程序在请求 /contextPath 时不重定向到 https 而不使用尾部斜杠

[英]Spring Boot application with embedded Tomcat behind reverse proxy not redirecting to https when asking for /contextPath without trailing slash

这个问题似乎已被多次询问,但对于这种特殊情况,我还没有找到合适的解决方案。

该应用程序是使用嵌入式 Tomcat 服务器并在 Openshift 上运行的 Spring Boot 1.5.x。 后者有一个带有 HTTPS 路由的路由器,它终止 TLS 隧道并通过 HTTP 将流量转发到应用程序 pod。 此外,它插入 X-Forwarded- 标头(包括 X-Forwarded-Proto 标头),以便使用 https 协议组成应用程序重定向。

我在 Spring Boot 应用程序中配置server.use-forward-headers: true并对其进行了测试:

1) OK -> https://ocproute/myapp/将 302 重定向到我的主页,保持 https 协议(Tomcat RemoteIpValve 处理了它)。

2) FAIL -> https://ocproute/myapp (注意没有尾部斜杠)将 302 重定向到http://ocproute/myapp/正如您所看到的,它将协议更改为 http,因为尚未调用 RemoteIpValve) .

日志显示 Tomcat 的 Http11InputBuffer 接收到请求,并在某些时候重定向它而不考虑 X-Forwarded-Proto 标头。

如何解决这个问题?

2019-06-03T17:31:59.230 ( -  -  -  -  - ) o.a.t.u.n.NioEndpoint DEBUG - Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@1511311d:org.apache.tomcat.util.net.NioChannel@5209052:java.nio.channels.SocketChannel[connected local=/0:0:0:0:0:0:0:1:8080 remote=/0:0:0:0:0:0:0:1:64871]], Read direct from socket: [595]
2019-06-03T17:31:59.230 ( -  -  -  -  - ) o.a.c.h.Http11InputBuffer DEBUG - Received [GET /myapp HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
X-Forwarded-Proto: https
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,es;q=0.7,cy;q=0.6
Cookie: JSESSIONID=4693A1F63CD3E18058F98E129D11CE57

]
...

你可以在你的 springboot 配置中设置这个道具:

server.tomcat.use-relative-redirects=true 

参考: https ://github.com/spring-projects/spring-boot/issues/22908

为了完成这项工作,我必须禁用自定义 Tomcat 上下文的上下文根重定向:

@Configuration
class TomcatConfiguration : EmbeddedServletContainerCustomizer {

    override fun customize(container: ConfigurableEmbeddedServletContainer) {
        val factory = container as TomcatEmbeddedServletContainerFactory
        factory.tomcatContextCustomizers = listOf(CustomCustomizer())

    }

    class CustomCustomizer : TomcatContextCustomizer {
        override fun customize(context: Context) {
            context.mapperContextRootRedirectEnabled = false
            context.addServletContainerInitializer(WsSci(), null)
        }
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM