【问题标题】:Spring Boot: Tomcat redirects to HTTPS 8443, no matter which HTTPS port I specifySpring Boot:无论我指定哪个 HTTPS 端口,Tomcat 都会重定向到 HTTPS 8443
【发布时间】:2021-05-02 16:36:37
【问题描述】:

我使用一种相当标准的方法将 Spring Boot 的嵌入式 Tomcat 从 HTTP 重定向到 HTTPS,这在许多教程中都有重复。该方法非常适用于端口 HTTP 8080 和 HTTPS 8443,这些端口也在本教程中作为示例重复。但是,将这些端口的数量更改为较少使用的值会产生许多问题,如下所述。

教程中的方法如下。应用属性:

server.http.port=8080
server.http.interface=0.0.0.0

server.port: 8443
server.ssl.enabled: true
server.ssl.key-store: classpath:selfsigned.jks
server.ssl.key-store-password: password
server.ssl.key-store-type: JKS
server.ssl.key-alias: selfsigned

然后是附加HTTP端口的配置:

@Component
public class HttpServer {
    @Value("${server.port}") int HTTPS_PORT;
    
    @Bean
    public ServletWebServerFactory servletContainer(@Value("${server.http.port}") int httpPort) {
        Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
        connector.setPort(httpPort);
        connector.setRedirectPort(HTTPS_PORT);
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
            @Override
            protected void postProcessContext(Context context) {
                ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
            }
        };
        tomcat.addAdditionalTomcatConnectors(connector);
        return tomcat;
    }
}

最后是安全配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http.cors().and().csrf().disable();
        http.requiresChannel().anyRequest().requiresSecure();
        http.headers().frameOptions().sameOrigin();
        http.portMapper()
                .http(Integer.parseInt(Prop.get("server.http.port")))
                .mapsTo(Integer.parseInt(Prop.get("server.port")));
    }
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

与教程的唯一区别是我禁用扫描 TomcatServletWebServerFactory 中的 Jar 清单文件,否则如果包含 tomcat-embed-jasper 则会出现问题(请参阅 here)。

这个:

server.http.port=8080
server.port: 8443

正如我所说,在教程中完美运行。这个:

server.http.port=8080
server.port: 5001

仍然重定向到 HTTPS 8443,但 8443 处没有任何内容,因为 Tomcat 在 8080 和 5001 处侦听:

INFO 7360 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 5001 (https) 8080 (http) with context path ''

我扫描了我的应用程序中的每个文件 8443,包括源代码和二进制文件。那里没有8443 的单个实例。我还使用调试器来验证setPort()setRedirectPort()portMapper() 中的值是否正确。

这个:

server.http.port=5000
server.port: 5001

产生:

0:0:0:0:0:0:0:1 - - [28/Jan/2021:18:44:46 +0100] "GET /a HTTP/1.1" 302 -
0:0:0:0:0:0:0:1 - - [28/Jan/2021:18:44:46 +0100] "GET /a HTTP/1.1" 302 -
0:0:0:0:0:0:0:1 - - [28/Jan/2021:18:44:46 +0100] "GET /a HTTP/1.1" 302 -
0:0:0:0:0:0:0:1 - - [28/Jan/2021:18:44:46 +0100] "GET /a HTTP/1.1" 302 -
...

直到浏览器抱怨重定向过多。

该站点在 localhost 上进行了测试,证书无效,因此 Chrome 请求安全例外。尽管如此,Chrome 还是将该站点置于 HTTP 严格传输安全中,这可以在 chrome://net-internals/#hsts 进行验证。是不是,Spring Boot 在 HSTS 标头中发送了一些内容,导致重定向到 8443?

总而言之,80808443 似乎有些特殊并在某处声明,可能在 Tomcat 或 Spring Boot 中。 如何摆脱这些默认设置? 任何调试方式,例如重定向背后的原因?增加Tomcat、Spring Boot日志的详细程度?

更新 1 为了禁用 HSTS,我修改了安全代码:

    http.headers().frameOptions().sameOrigin()
            .httpStrictTransportSecurity().disable();

并从 Chrome 的 HSTS 中删除了 localhost,但没有帮助。

更新 2 当应用程序在具有有效证书的外部服务器上运行时,问题仍然存在。

项目依赖:

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>compile</scope>
    </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>org.projectreactor</groupId>
        <artifactId>reactor-spring</artifactId>
        <version>1.0.1.RELEASE</version>
    </dependency>

【问题讨论】:

  • 浏览器记得以前的永久重定向,你确定这不是你的情况吗?
  • 我在隐身模式下进行了测试,检查/网络/禁用缓存。我猜它可以防止缓存重定向,但我不确定。
  • 你解决了吗?我碰巧有同样的问题...
  • 最近,我运行了一个带有备用端口的并行(测试)服务器,尽管我对此表示怀疑,但它确实有效。我没有在我知道的那个方向上做任何特别的事情。变化的主要是版本:操作系统、Java 机器、Spring Boot、Jasper 等。当然,也可能是某些“流氓”缓存在某处过期,但我不知道它可能是什么。

标签: spring spring-boot tomcat hsts


【解决方案1】:

无论您配置哪个端口,spring 团队都坚持使用 8443 是没有意义的。详情见 https://github.com/spring-projects/spring-security/issues/8140 https://github.com/spring-projects/spring-boot/issues/6140

【讨论】:

    猜你喜欢
    • 2018-08-23
    • 2014-09-04
    • 2016-11-06
    • 2014-12-13
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    • 2015-11-20
    • 2014-12-26
    相关资源
    最近更新 更多