I'm using Elastic Beanstalk to deploy a Spring Boot web server, running behind an application load balancer (Elastic Load Balancer). A business rule is that this web server should only be contacted through HTTPS. So any HTTP request must first be forwarded to HTTPS.
Based on this article from Amazon, I should simply inspect the x-forwarded-for
and x-forwarded-proto
headers, which are set by the load balancer. These headers contain information about the original request, made by the client to the load balancer.
So I started looking for built-in ways for Spring Boot (I'm using the built-in Tomcat server, btw) to inspect those two headers and do the redirection, without having to write too much code myself. The Spring Boot (we're on version 1.4) docs state to use the following application properties:
security.require_ssl=true
server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto
Testing this with Postman gives me an HTTP 200 where I should be getting a 301/302 redirect. I suspect this is due to me using Spring Security. To make it work with Spring Security, I could add this to my WebSecurityConfigurerAdapter
:
http.requiresChannel().anyRequest().requiresSecure();
But now my headers are ignored and all requests are forwarded to HTTPS, even if the original request was HTTPS already. So now nothing works.
The answer by Rodrigo Quesada here seems to be what I need, but it still doesn't respect my headers, for some reason. This request still gives me a redirect instead of a 200:
GET / HTTP/1.1
Host: localhost:8080
X-Forwarded-Proto: https
X-Forwarded-For: 192.168.0.30
There are many other solutions here and on other websites, using another intermediary web server, or configuring NGINX or Apache on AWS to do the redirection. But I'm using Tomcat already, why would I want to configure yet another web server.
So how can I actually configure Spring Boot/Tomcat/Spring Security in a Spring-way to do this redirection? Is there a way to extend the behavior of the requiresSecure()
function so that it takes into account my request headers? Or even better, are there any Spring Security alternatives to the application properties I tried?