一、问题描述

在服务协议由 http 迁移至 https 时,我发现线上环境报错

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
Caused by: java.security.cert.CertificateExpiredException: NotAfter: Sat May 30 18:48:38 CST 2020

二、问题排查

根据报错 CertificateExpiredException: NotAfter: Sat May 30 18:48:38 CST 2020 是因为证书过期,我立即联系客户技术部确认他们的证书是否过期,经查证没有过期

但是在生产和测试环境都报证书过期错误,奇怪的是本地环境可以正常访问

于是我在 https://whatsmychaincert.com/ 验证其证书链是否有问题,果然经查证其证书链中有过期的证书:

所以原因定位在客户服务器的证书链中存在过期证书

三、什么是证书链

简单来说,当客户端访问 TLS 服务器时,服务端会发送一个证书给客户端来证明其身份,客户端需要构建一条由服务端证书到根证书的证书链,以便对其进行验证。服务端很贴心,帮客户端返回了一条证书链

如果服务端的证书链是这个样子:

在这里插入图片描述
那么对于现代浏览器或客户端来说,C 没有过期就可以了,直接忽略了 D

但对于 OpenSSL 1.0.x or GnuTLS 来说,它们会一直检测到 D,因为 D 已经失效了 2019(现在是 2021 年),所以会返回证书过期

四、解决方案

鉴于此,我赶紧去生产和测试机器查了一下 openssl 的版本,果然是 OpenSSL 1.0.x,和上述结论一致。本地环境用的是 LibreSSL 2.8.3,因此访问没有问题

4.1 直接禁用 ssl 证书校验

```java // 在调用SSL之前需要重写验证方法,取消检测 SSL X509TrustManager trustManager = new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; SSLContext ctx = SSLContext.getInstance(SSLConnectionSocketFactory.TLS); ctx.init(null, new TrustManager[]{trustManager}, null); SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE); Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", socketFactory).build(); // 创建ConnectionManager,添加Connection配置信息 connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); connectionManager.setMaxTotal(MAX_CONNECTION_NUM); connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE); HttpClients.custom().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).build();

4.2 更新服务器 openssl 库版本

4.3 更新服务端证书

访问 https://whatsmychaincert.com/,直接点击链接下载新证书,安装即可

证书类型验证网站:https://csr.chinassl.net/ssl-checker.html

证书过期问题:https://whatsmychaincert.com

https://www.agwa.name/blog/post/fixing_the_addtrust_root_expiration#2099-client_operators

一、问题描述在服务协议由 http 迁移至 https 时,我发现线上环境报错javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failedCaused by: java.security.cert.Certif
SSL 证书 认证失败 java x.net. ssl . SSL HandshakeException: java .security.cert.CertificateException: 解决方法
在进行单元测试发现Caused by: java x.net. ssl . SSL HandshakeException: java .security.cert.CertificateException: java .sec 解决方法: "jdbc:mysql://127.0.0.1:3306/ java _16blogdemo?characterEncoding=utf-8&use SSL =true"; 将上面的use SSL 改为false即可 。 "C:\Program Files (x86)\Jav