Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to redirect automatically to https with Spring Boot

How I can easily configure the embedded tomcat server to redirect all http traffic to https? I have Spring Boot running on an ec2 instance that is behind an elastic load balancer. I have configured the ELB to handle ssl for me (which is awesome) and it sets the X-FORWARDED-PROTO header to "https". I want to detect when that isn't set, and redirect the user to force them to use https if they aren't already.

So far, I have tried adding the following to my application.properties file with no luck:

server.tomcat.protocol-header=x-forwarded-proto
security.require-ssl=true
like image 427
kgreenek Avatar asked Mar 25 '14 04:03

kgreenek


2 Answers

My answer is a little late but I just recently had this problem and want to post a solution which worked for me.

Originally, I thought that setting tomcat up to use the X-Forwarded headers would suffice but the RemoteIPValve from Tomcat, which should normally handle this case, didnt work for me.

My solution was to add an EmbeddedServletContainerCustomizer and add a ConnectorCustomizer: (note that I am using Tomcat 8 here)

@Component
public class TomcatContainerCustomizer implements EmbeddedServletContainerCustomizer {

    private static final Logger LOGGER = LoggerFactory.getLogger(TomcatContainerCustomizer.class);

    @Override
    public void customize(final ConfigurableEmbeddedServletContainer container) {
        if (container instanceof TomcatEmbeddedServletContainerFactory) {
            final TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container;
            tomcat.addConnectorCustomizers(connector -> { 
                connector.setScheme("https");
                connector.setProxyPort(443);
            });
            LOGGER.info("Enabled secure scheme (https).");
        } else {
            LOGGER.warn("Could not change protocol scheme because Tomcat is not used as servlet container.");
        }
    }
}

The important thing is that you not only set the Scheme to https but also the ProxyPort without which all internal redirects from Spring Boot were routed to port 80.

like image 116
Dennis Avatar answered Sep 20 '22 05:09

Dennis


The configuration property security.require-ssl doesn't work when basic authentication is disabled (at least on old versions of Spring Boot). So you probably need to secure all the requests manually with code similar to this one:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Inject private SecurityProperties securityProperties;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        if (securityProperties.isRequireSsl()) http.requiresChannel().anyRequest().requiresSecure();
    }
}

You can check my full answer here: Spring Boot redirect HTTP to HTTPS

like image 28
Rodrigo Quesada Avatar answered Sep 21 '22 05:09

Rodrigo Quesada