我们为集群中的每个服务都有证书,用于服务间通信。当这些证书过期(几天)时,我们开始收到握手错误。在我们从 SpringBoot 2.7.6 迁移到 SpringBoot 3.1.2(也在 3.2.0 中尝试过)以及 Java 11 迁移到 17 后,这种情况开始发生。
错误消息有多种“类型”,一些显示 SSLHandshakeException(如下),另一些显示“PKIX 路径验证失败”
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
当服务证书即将过期时,它会在服务 pod 中自动更新,然后脚本替换密钥库并调用将重新加载密钥库并重新启动 tomcat 连接器的端点。这以前有效,但现在不行了。
查看日志时最引人注目的一件事是以下消息:
Connector [https-jsse-nio-8280], TLS virtual host [_default_], certificate type [UNDEFINED] configured from keystore [**/home/.keystore**] using alias [serverkey] with trust store [null]
但是在 application.properties 中我们有类似的东西:
server.keystore=/keystore/serverkeystore.p12
server.truststore=/truststore/truststore.p12
是什么让我们认为当tomcat重新启动时,它试图从错误的位置获取证书,即/home/.keystore,而不是application.properties中设置的证书。
作为解决方案,我们创建了一个实现 TomcatConnectorCustomizer 的类,该类填充了 application.properties 中找到的所有必要信息,并创建了一个 ServletWebServerFactory bean,将该自定义连接器添加到 TomcatServletWebServerFactory 并返回它。 像这样的东西:
@Bean
ServletWebServerFactory servletContainer(@Autowired SSLConnectorCustomization sslConnectorCustomization)
{
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addConnectorCustomizers(sslConnectorCustomization);
return tomcat;
}
private SSLHostConfig getNewSSLHostConfig(SSLHostConfig config)
{
SSLHostConfig newConfig = new SSLHostConfig();
:
newConfig.setTruststoreFile("/truststore/truststore.p12");
:
SSLHostConfigCertificate cert = new SSLHostConfigCertificate(newConfig, SSLHostConfigCertificate.Type.RSA);
:
cert.setCertificateKeystoreFile("/keystores/serverkeystore.p12");
:
newConfig.addCertificate(cert);
return newConfig;
}
当我们迁移到 java 17 时,我们对代码进行了很多更改。在这一点上,我们将 Apache http 替换为 http5,我相信我们可能错过了一些东西或一些新配置,我不知道。事实上,如果没有解决方法,它在 2.x 中可以工作,而在 3.x 中则无法工作。实际上它看起来像一个 Spring 问题,但因为它在 SB 3.2 中仍然给出相同的结果有人知道这里到底发生了什么以及如何在没有解决方法的情况下修复它吗?
我们成功地在 SB 3.1 中修复了这个问题,方法是基于 Hakan54 给出的实现创建 TomcatConnectorCustomizer 实现 https://stackoverflow.com/a/78347946/5468484.
但是,自从我们升级到 SB 3.2 以来,我们将解决方案改为使用 SSL 捆绑包。它更加干净并且工作完美。 https://spring.io/blog/2023/06/07/secure-spring-boot-applications-with-ssl
因此,如果您使用 SB >= 3.2,请采用第二种解决方案。如果你陷入困境<3.2, go for the first one.