Spring Boot 2.x升级3.x后出现bad_certificate握手异常问题
Spring Boot 3.x + Java 17 证书重载失效问题
集群内每个服务都配有服务间通信证书,当证书即将过期(提前数天)时,会出现握手错误。该问题始于将Spring Boot从2.7.6升级至3.1.2(也尝试过3.2.0)、Java从11升级至17之后。
出现的错误类型包括:
- SSLHandshakeException:
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
PKIX path validation failed
原本的证书更新流程是:证书即将过期时,会在服务Pod中自动更新,随后脚本替换密钥库并调用端点重新加载密钥库、重启Tomcat连接器。这套流程在Spring Boot 2.x中正常工作,但升级后失效。
查看日志发现异常:
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读取证书。
我们目前的临时解决方案是:实现TomcatConnectorCustomizer类,手动填充application.properties中的所有必要配置,再创建ServletWebServerFactory Bean,将自定义连接器添加到TomcatServletWebServerFactory中。代码示例如下:
自定义ServletWebServerFactory Bean
@Bean ServletWebServerFactory servletContainer(@Autowired SSLConnectorCustomization sslConnectorCustomization) { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat.addConnectorCustomizers(sslConnectorCustomization); return tomcat; }
构建SSLHostConfig的核心代码
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,推测可能遗漏了某些配置。这套流程在Spring Boot 2.x中正常运行,但3.x版本必须依赖上述临时方案才能工作,且Spring Boot 3.2中问题依旧。
请问问题根源是什么?如何不依赖临时方案解决该问题?
内容的提问来源于stack exchange,提问作者Alexandre Hermida
相关产品推荐
相关产品推荐

