You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Amazon Corretto JDK 11+Tomcat9从MMC读取证书3分钟后SSL请求失败

问题背景

使用Amazon Corretto JDK 11 + Tomcat 9.x,配置Tomcat从Windows MMC(Windows-ROOT信任库)读取SSL证书,应用前3分钟可正常处理Web服务请求,但3分钟后所有请求失败,报错如下:

javax.net.ssl|ERROR|24 89|https-openssl-apr-8443-exec-4|2024-02-01 10:10:26.775 EST|TransportContext.java:341|Fatal (CERTIFICATE_UNKNOWN): PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target (
"throwable" : {
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
at java.base/sun.security.validator.Validator.validate(Validator.java:264)
at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:313)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:222)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:129)
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
... 154 more}

添加以下Java参数开启调试日志(指定信任库类型为Windows-ROOT):

-Djavax.net.ssl.trustStoreType=Windows-ROOT
-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager
-Djava.security.debug=certpath

调试发现证书被加载两次:第一次加载360个(对应Windows MMC根证书),第二次仅加载150个,问题出现在第二次加载后。通过日志中X509TrustManagerImpl.java:79|adding as trusted certificates条目统计证书数量。

将目标证书加入JDK的cacerts文件后问题解决,但存在两个疑问:

  1. 第二次加载的证书来自哪里?
  2. 若来自cacerts,为何指定Windows-ROOT时仍会加载该文件?

问题解答

1. 第二次加载的证书来源

第二次加载的150个证书确实来自JDK默认的cacerts信任库。

2. 指定Windows-ROOT仍加载cacerts的原因

这是Corretto JDK 11结合Tomcat运行时的特定逻辑导致的,核心原因包括:

  • Tomcat线程池触发SSL上下文重建:Tomcat的APR/nio线程池在运行一段时间后,可能触发SSL上下文重新初始化。第一次初始化严格遵循javax.net.ssl.trustStoreType=Windows-ROOT配置,加载系统根证书;但后续重建时,部分场景下JVM参数未被正确传递,导致JDK fallback到默认的cacerts信任库。
  • Windows-ROOT信任库的线程访问限制:Corretto JDK的Windows-ROOT实现依赖Windows CryptoAPI,当Tomcat工作线程处于特殊上下文(如线程重新分配)时,可能无法正常访问系统证书存储,JDK会自动切换到cacerts作为备选。
  • Tomcat配置优先级冲突:如果server.xml的<Connector>节点中隐式配置了truststoreFile(即使未显式写值),会覆盖JVM层面的trustStoreType配置,导致后续加载cacerts。

验证与修复建议

  • 显式配置Tomcat Connector信任库:在server.xml的HTTPS Connector中直接指定信任库类型,避免依赖JVM参数的传递问题:
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                         type="RSA"
                         truststoreType="Windows-ROOT"/>
        </SSLHostConfig>
    </Connector>
    
  • 禁用默认信任库 fallback:添加JVM参数-Djavax.net.ssl.trustStore=NONE,强制JDK仅使用指定的Windows-ROOT信任库。
  • 升级Corretto JDK版本:部分旧版Corretto 11存在Windows信任库的线程安全问题,升级到最新稳定版可解决上下文切换导致的加载异常。

内容的提问来源于stack exchange,提问作者Mounika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:15:25