错误信息
PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed
也可能输出为
- javax.net.ssl.SSLHandshakeException: (certificate_expired) PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed
JDK 21 及更高版本会把 TLS 告警放在前面:“(certificate_expired) PKIX path validation failed: …”。根本原因所在的行是“java.security.cert.CertificateExpiredException: NotAfter: <date>”(或 CertificateNotYetValidException: NotBefore: <date>),日期按 JVM 的时区显示。
Java (JSSE) — SSLHandshakeException caused by CertPathValidatorException / CertificateExpiredException
含义
Java 构建出了一条通往信任锚的证书路径,但验证时日期检查未通过:按 JVM 的当前时间,路径中有一张证书不在其有效期内。出现的是“path validation”(路径验证)而不是“path building”(路径构建),这说明信任没有问题,问题出在日期上。嵌套的 CertificateExpiredException 或 CertificateNotYetValidException 会指出越过的是哪一个边界。
原因
服务器证书(或中间证书)已过期
常见没有续期,或者续期后的证书没有部署到 Java 所连接的端点上(通常是内部负载均衡器,或带有独立密钥库的 Java 服务器)。
证书链经由自定义信任库中的过期证书构建
偶见直接固定了旧的中间证书或服务器证书的信任库,在证书过期后仍会拿它来验证。
JVM 所在主机的时钟不准
偶见宿主机时钟发生漂移的虚拟机和容器,会让当前有效的证书看起来已过期或尚未生效。
刚签发的证书遇上走慢的时钟
罕见从“此刻”起生效的证书,在时钟慢了几分钟的客户端上会验证失败;正因如此,大多数 CA 会把 notBefore 稍微提前一点,而私有 CA 往往不会。
修复方法
- 1.
查看最内层的异常原因
NotAfter 或 NotBefore 日期会告诉你,是证书过期了,还是时钟不准。
text Caused by: java.security.cert.CertificateExpiredException: NotAfter: Tue Apr 01 00:00:00 UTC 2025 -> a certificate in the chain expired on that date Caused by: java.security.cert.CertificateNotYetValidException: NotBefore: ... -> not valid yet: check the clock of this machine - 2.
检查服务器发送的每一张证书
打印服务器所发送证书链中每张证书的到期日期;过期的那张就替换掉。
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts 2>/dev/null \ | awk '/BEGIN CERT/{n++; f="c" n ".pem"} /BEGIN CERT/,/END CERT/{print > f}' for f in c*.pem; do openssl x509 -in "$f" -noout -subject -enddate; done - 3.
清理自定义信任库
列出信任库中的条目及其有效期,删除或替换固定在其中的过期证书。
bash # Expired or pinned certificates in a custom trust store keytool -list -v -keystore app-truststore.p12 -storepass changeit | grep -E 'Alias name|Valid until|Owner' keytool -delete -alias old-corp-root -keystore app-truststore.p12 -storepass changeit