SpringBoot 2.0 如何在 http 和 https 端口上运行,并将 http 重定向到 https 端口?

4
我有一个使用http和https协议的SpringBoot 2.0应用程序。因此,它在端口9080上提供http协议,在端口9443上提供https协议,这很好地工作着。我唯一想要的是,如果用户输入例如:http://localhost:9443/e1,则进行重定向。
总结如下: http://localhost:9080/e1 >> 按预期工作。 https://localhost:9443/e1 >> 按预期工作。 http://localhost:9443/e1 >> 引发错误Bad Request. This combination of host and port requires TLS.,但应该被重定向到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;
    }
}

我的application.properties文件如下:

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

也许有人有解决这个问题的想法。谢谢,祝你有美好的一天 :-)


您可以通过使用TomcatEmbeddedServletContainerFactory对上下文进行后处理来实现此操作。 - IMParasharG
我使用的是SpringBoot 2.1.1,但这个类在SpringBoot > 2.0中不可用。 - Andreas Gottardi
是的,真的。使用TomcatServletWebServerFactory。我正在编写代码。 - IMParasharG
可能是重复问题 https://dev59.com/OV8d5IYBdhLWcg3wlzD6 - IMParasharG
嗯,我已经尝试过了,但是在可能的重复问题中提到的解决方案总是重定向到https。我只想在用户意外使用https端口的http协议时进行重定向。如果使用http协议和端口,则服务器应通过http响应。但是感谢您提供的链接,我会尝试让它运行并在成功后在此发布答案! - Andreas Gottardi
显示剩余2条评论
3个回答

1
如果您正在使用嵌入式Tomcat,您可以修改返回消息以包含重定向头部。
例如,对于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);

请注意,这是静态值,只能重定向到一个URL,除非您提供自己的安全通道实现。

0

对于Springboot 2.x,您可以使用以下内容。

    @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;
}

0
也许你可以尝试将代码放在配置类中,我就是这样做的,并且没有问题。我使用的版本是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;
    }
}

如果您仍然无法解决问题,我非常抱歉,希望您能尽快解决这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接