-
Notifications
You must be signed in to change notification settings - Fork 41.4k
Description
Affects: Spring Boot v2.2.1.RELEASE
context path redirect causes protocol downgrade to http
I'm trying to run a basic Spring Boot application behind a proxy and with a context path, because later it will run on a server with other applications and inside a Docker container.
I'm having difficulties with the redirect to the context path. Here is a structural overview of the system:
+--------+ https +-------+ http +--------+
| Client | ------> | Proxy | ------> | Spring |
+--------+ +-------+ +--------+
When sending a request with the schema https://<proxy-url>/<context-path>
, the Spring redirects the client to http://<proxy-url>/<context-path>/
. So it downgrades the protocol from https to http.
I honestly don't know whether this is a bug or intended behavior. Is there a way to make Spring redirect to https instead of http. The proxy redirect contains the correct X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Port headers.
The Curl output below shows that Spring reads the headers properly when adding the slash at the end of the context path. The Curl requests talk directly to Spring and I did set the headers manually to emulate the proxy. I also attached the code of the test application and a screenshot of the redirect within Chrome.
Request and redirect screenshot
Curl
Slash at the end of the context path
C:\Users\<user>>curl -v -H "X-Forwarded-Proto: https" -H "X-Forwarded-Port: 443" -H "X-Forwarded-Host: <host>" http://localhost:8081/hweproxy/
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8081 (#0)
> GET /hweproxy/ HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/7.55.1
> Accept: */*
> X-Forwarded-Proto: https
> X-Forwarded-Port: 443
> X-Forwarded-Host: <host>
>
< HTTP/1.1 200
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< Strict-Transport-Security: max-age=31536000 ; includeSubDomains
< X-Frame-Options: DENY
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 33
< Date: Tue, 11 Aug 2020 09:32:52 GMT
<
https://<host>/hweproxy/* Connection #0 to host localhost left intact
No slash at the end of the context path
C:\Users\<user>>curl -v -H "X-Forwarded-Proto: https" -H "X-Forwarded-Port: 443" -H "X-Forwarded-Host: <host>" http://localhost:8081/hweproxy
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8081 (#0)
> GET /hweproxy HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/7.55.1
> Accept: */*
> X-Forwarded-Proto: https
> X-Forwarded-Port: 443
> X-Forwarded-Host: <host>
>
< HTTP/1.1 302
< Location: http://localhost:8081/hweproxy/
< Transfer-Encoding: chunked
< Date: Tue, 11 Aug 2020 09:19:51 GMT
<
* Connection #0 to host localhost left intact
Basic Spring Boot application code
Java Code
@SpringBootApplication
public class SpringPoC {
public static void main(String[] args) {
SpringApplication.run(SpringPoC.class, args);
}
}
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("**").permitAll()
.and()
.cors()
.and()
.csrf()
.disable();
}
}
@RestController
@RequestMapping("/")
public class DummyController {
@GetMapping
public ResponseEntity<?> dummyEndpoint(HttpServletRequest req) {
return ResponseEntity.ok(req.getRequestURL());
}
}
application.properties
server.port = 8081
server.servlet.context-path = /hweproxy
server.forward-headers-strategy = FRAMEWORK
server.tomcat.remoteip.internal-proxies = \\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>spring-poc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spring Prove of Concept</name>
<url>http://example.com</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
</project>