简体   繁体   中英

Spring Boot/Tomcat: HTTP -> HTTPS 301 Redirects

Using Spring Boot and/or underlying Tomcat connectors, I'm looking to redirect all HTTP requests to HTTPS using 301 redirects, not 302s. I currently have a solution that works exactly the way I want it except that it returns 302s instead of 301s. Here's what it looks like:

@Bean
public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
        @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(createHttpConnector());
    return tomcat;
}

private Connector createHttpConnector() {
    Connector connector = new Connector(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL);
    connector.setScheme("http");
    connector.setSecure(false);
    connector.setPort(80);
    connector.setRedirectPort(443);
    return connector;
}

(My default connector is HTTPS, defined in application.properties as I've seen suggested before throughout the interwebs.)

I require 301s to be returned because I previously didn't have an HTTPS option, but now I do (and it's mandatory) and that option utilizes HTML5 application caching , which won't work if the user is offline and attempts to visit a HTTP URL; as I understand it, browsers like Chrome do not cache 302 redirects, but do cache 301s, so switching to returning 301s consistently should make the website available offline even when a request is made for HTTP and not HTTPS, like in the case of old bookmarks or lazy linking to my .com address without specifying a protocol.

This SO question really gets at what I'm looking for, but it's unanswered and Tomcat-specific; if there's anything specific to Spring or Spring Boot that I can utilize to accomplish this, I'm open to that too. For example, I'm not currently using Spring Security, but I'd be willing to throw that into the mix if necessary.

Any ideas? Thanks in advance for any help.

It's been over a year since I originally posted this question, but I just pieced together this comment and this comment to other SO questions to get 301 redirects. Here's what I came up with, with an emphasis on the addContextCustomizers bit:

@Bean
public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
        @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(createHttpConnector());
    tomcat.addContextCustomizers((TomcatContextCustomizer) context -> {
        NullRealm realm = new NullRealm();
        realm.setTransportGuaranteeRedirectStatus(301);
        context.setRealm(realm);
    });
    return tomcat;
}

Unfortunately, this alone doesn't seem to solve the HTML5 application caching issue, but I'll keep digging on that front. What's another year anyway...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM