4

I have a SpringBoot 2.0 application which uses http and https. So on port 9080 it serves the http protocol and on port 9443 https, which works fine. The only thing I'd like to have is a redirection, if a user types in for example: http://localhost:9443/e1

To sum it up:

http://localhost:9080/e1 >> works as expected.

https://localhost:9443/e1 >> works as expected.

http://localhost:9443/e1 >> brings the error Bad Request. This combination of host and port requires TLS. but should get redirected to https://localhost:9443/e1.

@SpringBootApplication
@EnableScheduling
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    /* HTTP(S) configuration */

    @Value("${http.port}")
    private int httpPort;

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(createStandardConnector());
        return tomcat;
    }

    private Connector createStandardConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setPort(httpPort);
        return connector;
    }
}

My application.properties is

server.port=9443
http.port=9080
server.ssl.enabled=true
server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=my_passowrd
server.ssl.key-alias=my_alias

Maybe someone has an idea on how to solve it. Thanks and have a good day :-)

  • You can do this by post-processing the Context using a TomcatEmbeddedServletContainerFactory – IMParasharG Mar 07 '19 at 14:40
  • I use SpringBoot 2.1.1 and this class is not available in SpringBoot > 2.0. – Andreas Gottardi Mar 07 '19 at 14:46
  • Yes true. Use TomcatServletWebServerFactory. I am writing code – IMParasharG Mar 07 '19 at 14:48
  • possible duplicate https://stackoverflow.com/questions/26655875/spring-boot-redirect-http-to-https – IMParasharG Mar 07 '19 at 14:52
  • Hm, I have tried it, but the solution mentioned in the possible duplicate always redirects to https. I just want to redirect in case the user accidentally used the http protocol with the https port. If http protocol and port is used, the server should respond via http. But thanks for the link, I'll try to get it running and post the answer here, if successful! – Andreas Gottardi Mar 07 '19 at 18:48
  • The code in your question actually fixed a problem I had. I love it when that happens. – thonnor Jan 08 '20 at 16:15
  • @AndreasGottardi Did you ever figure out how to go to https if the user entered http on the https port? – SledgeHammer Mar 26 '20 at 18:56

3 Answers3

1

If you are using embedded Tomcat, you can modify returned message to contain redirect header.

E.g. for Tomcat 9.0.x:

TLSClientHelloExtractor.USE_TLS_RESPONSE = ("HTTP/1.1 302 \r\n"
    + "Content-Type: text/plain;charset=UTF-8\r\n" + "Location: https://" + hostnamePort + "\r\n"
    + "Connection: close\r\n" + "\r\n" + "Bad Request\r\n"
    + "This combination of host and port requires TLS.\r\n"
    + "Please access this URL with HTTPS scheme.\r\n").getBytes(StandardCharsets.UTF_8);

Note that this is static value and can redirect only to one URL, unless you provide your own secure channel implementation.

mota
  • 193
  • 2
  • 12
0

For Springboot 2.x you can use the following.

    @Bean
public TomcatServletWebServerFactory tomcatFactory() {
    TomcatServletWebServerFactory tomcatFactory = 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);
        }
    };

    tomcatFactory.addAdditionalTomcatConnectors(redirectConnector());
    return tomcatFactory;
}

private Connector redirectConnector() {
    Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    connector.setScheme("http");
    connector.setPort(80);
    connector.setSecure(false);
    connector.setRedirectPort(443);

    return connector;
}
ejazazeem
  • 542
  • 7
  • 10
0

Maybe you can try to put your code in the configuration class, I did it this way and there is no problem.the version I use is 2.3.4.RELEASE

@Configuration
public class TomcatConfig {
    @Value("${server.http.port}")
    private int httpPort;

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(createStandardConnector()); // 添加http
        return tomcat;
    }

    private Connector createStandardConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setPort(httpPort);
        return connector;
    }
}

If you still can’t solve your problem, I’m very sorry, I hope you can solve this problem as soon as possible

LHZ
  • 1
  • 1