12

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
kgreenek
  • 4,986
  • 3
  • 19
  • 30
  • Do you have a secure application (is Spring Security on the classpath and is it intercepting your requests)? Note that even then the redirect is not automatic (Spring Security works with HSTS which requires the client to understand and follow the directives in teh headers). – Dave Syer Mar 25 '14 at 12:37
  • 1
    Hi. Did you solve this? We are facing a similar problem. We have an ec2 load balancer that terminates ssl and uses http back to a Spring boot application. We could remove the https listener from the load balancer but we would rather have do a redirect to https. – hermansen Dec 10 '14 at 10:26
  • possible duplicate of [Spring Boot redirect HTTP to HTTPS](http://stackoverflow.com/questions/26655875/spring-boot-redirect-http-to-https) –  Mar 25 '15 at 22:14

4 Answers4

10

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.

Jacob van Lingen
  • 8,989
  • 7
  • 48
  • 78
Dennis
  • 101
  • 1
  • 4
2

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

Community
  • 1
  • 1
Rodrigo Quesada
  • 1,460
  • 1
  • 14
  • 20
0

You will need a keystore file and few config classes.

The below link explains it in detail.

Https on embedded tomcat

Sezin Karli
  • 2,517
  • 19
  • 24
  • In this scenario, AWS load balancers are used and SSL is handled on AWS load balancers. So, there is no need for a keystore file. – Halil Dec 08 '18 at 20:09
0

Spring Boot 2.0 redirection of http to https:

Add the following to the @Configuration

   @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
            @Override
            protected void postProcessContext(Context context) {
                SecurityConstraint securityConstraint = new SecurityConstraint();
                securityConstraint.setUserConstraint("CONFIDENTIAL");
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
                securityConstraint.addCollection(collection);
                context.addConstraint(securityConstraint);
            }
        };
        tomcat.addAdditionalTomcatConnectors(redirectConnector());
        return tomcat;
    }

    private Connector redirectConnector() {
        Connector connector = new Connector(
                TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
        connector.setScheme("http");
        connector.setPort(8080);
        connector.setSecure(false);
        connector.setRedirectPort(8443);
        return connector;
    }
conteh
  • 1,544
  • 1
  • 17
  • 39