如何在 Spring Boot 嵌入式 tomcat 中设置 HTTPS SSL 密码套件首选项

Posted

技术标签:

【中文标题】如何在 Spring Boot 嵌入式 tomcat 中设置 HTTPS SSL 密码套件首选项【英文标题】:How to set HTTPS SSL Cipher Suite Preference in Spring boot embedded tomcat 【发布时间】:2017-10-11 22:38:29 【问题描述】:

我尝试根据服务器首选项设置 HTTPS SSL 密码套件首选项,而不是根据客户端和服务器支持的最高强度通用密码套件自动选择。

我喜欢让服务器选择具有“TLS_ECDHE...”的服务器和客户端之间的共同点,以支持前向保密。 现在我在“www.ssllabs.com”中进行了测试,客户端浏览器会更喜欢具有“TLS_RSA...”而不是“TLS_ECDHE”的密码...

我注意到 java 8 支持设置密码套件首选项: http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#cipher_suite_preference

我假设 spring boot 嵌入式 Tomcat 将调用 Java 8 函数来选择密码

这是我在 spring boot application.properties 文件中设置服务器支持密码集所做的:

server.ssl.ciphers=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_SHA256,TLS_ECDHE_RSA_WITH_AES_128_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_SHA,TLS_ECDHE_RSA_WITH_AES_256_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_SHA384,TLS_ECDHE_RSA_WITH_AES_256_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_SHA,TLS_DHE_RSA_WITH_AES_128_SHA256,TLS_DHE_RSA_WITH_AES_128_SHA,TLS_DHE_DSS_WITH_AES_128_SHA256,TLS_DHE_RSA_WITH_AES_256_SHA256,TLS_DHE_DSS_WITH_AES_256_SHA,TLS_DHE_RSA_WITH_AES_256_SHA

希望有人可以指导我如何覆盖默认选择密码行为。

【问题讨论】:

【参考方案1】:

这是我在 Spring Boot 2.3.4.RELEASE 和 JDK 1.8 中的解决方案。 对我来说效果很好。

import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.AbstractHttp11Protocol;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HttpsConfiguration 

    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainerCustomizer() 
        return new WebServerFactoryCustomizer<TomcatServletWebServerFactory>() 
            @Override
            public void customize(TomcatServletWebServerFactory factory) 
                factory.addConnectorCustomizers(new TomcatConnectorCustomizer() 
                    @Override
                    public void customize(Connector connector) 
                        AbstractHttp11Protocol<?> httpHandler = ((AbstractHttp11Protocol<?>) connector.getProtocolHandler());
                        httpHandler.setUseServerCipherSuitesOrder(true);
                        httpHandler.setSSLProtocol("TLSv1.2");
                        httpHandler.setSSLHonorCipherOrder(true);
                        httpHandler.setCiphers("TLS_EMPTY_RENEGOTIATION_INFO_SCSV,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384");
                    
                );
            
        ;
    


【讨论】:

【参考方案2】:

您需要告诉连接器的底层协议处理程序使用服务器的密码套件顺序。您可以使用WebServerFactoryCustomizer

@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainerCustomizer() 
    return (factory) -> 
        factory.addConnectorCustomizers((c) -> 
            ((AbstractHttp11Protocol<?>) c.getProtocolHandler()).setUseServerCipherSuitesOrder(true));
    ;

【讨论】:

要将此解决方案升级到 Spring Boot 2.1.x,我只需要进行两个小改动:将 EmbeddedServletContainerCustomizer 替换为 WebServerFactoryCustomizer&lt;TomcatServletWebServerFactory&gt;,将 TomcatEmbeddedServletContainerFactory 替换为 TomcatServletWebServerFactory 另外,在 Spring Boot 2.0.7 和 2.1.3 之间的某个地方,setUseServerCipherSuitesOrder 的参数从 String 更改为 boolean。 setUseServerCipherSuitesOrder 现在收到一个布尔值

以上是关于如何在 Spring Boot 嵌入式 tomcat 中设置 HTTPS SSL 密码套件首选项的主要内容,如果未能解决你的问题,请参考以下文章

如何在嵌入式 tomcat 服务器上部署 Spring Boot Web 应用程序,来自 Spring Boot 本身

如何在 spring-boot 中拦截嵌入式 Tomcat 上的“全局”404

如何在嵌入式 Spring Boot Keycloak 中设置主题?

如何在 Spring Boot 集成测试中使用嵌入式 MongoDB

如何在 Spring Boot 中关闭嵌入式 Tomcat?

如何禁用嵌入式数据库 Spring-boot spring-data-jpa