简体   繁体   中英

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

This problem seems to have been asked multiple times but for this particular case I haven't found a proper solution.

The application is a Spring Boot 1.5.x that uses a embedded Tomcat server and runs on Openshift. The latter has a Router with an HTTPS route that terminates the TLS tunnel and forwards the traffic over HTTP to the application pod. In addition it inserts the X-Forwarded- headers (including the X-Forwarded-Proto header) so that the application redirects are composed using the https protocol.

I have configured server.use-forward-headers: true in the Spring Boot Application and tested it:

1) OK -> https://ocproute/myapp/ redirects 302 to my home page keeping the https protocol (the Tomcat RemoteIpValve took care of it).

2) FAIL -> https://ocproute/myapp (note there's no trailing slash) redirects 302 to http://ocproute/myapp/ As you can see it changed the protocol to http since the RemoteIpValve hasn't been invoked yet).

The logs show that Tomcat's Http11InputBuffer receives the request and at some point redirects it without taking into account the X-Forwarded-Proto header.

How can this be fixed?

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

]
...

you can set this prop in your springboot config:

server.tomcat.use-relative-redirects=true 

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

To make this work I had to disable the context root redirection customizing the Tomcat Context:

@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)
        }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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