JAVA后端线上环境调用接口出现证书不信任:PKIX path building failed

JAVA后端线上环境调用接口出现证书不信任:PKIX path building failed



前言

目前市面上,比如阿里云购买的HTTPS证书,在浏览器中是可信任的证书,但是对于JAVA程序而言,可能会出现以下错误:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1564)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:263)
	at java.net.URL.openStream(URL.java:1045)
	at TestUrl.main(TestUrl.java:13)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
	at sun.security.validator.Validator.validate(Validator.java:260)
	at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
	... 14 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

那么这个问题怎么排查并解决呢?小编试着从以下几个方面解决这个问题。


一、测试验证是否无法调通目标接口

1)在线上环境中编写接口测试类 TestUrl.java

vi TestUrl.java

复制并粘贴以下内容

import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

/**
*
* 接口连接性测试类
**/
public class TestUrl {

    public static void main(String[] args) {
       long lo = System.currentTimeMillis();
        URL url;
        try {
             // 修改URL地址
             url = new URL("https://xxxxx.xxxx.com/interface/v1/0/xxxxxx");
             InputStream in = url.openStream();
             System.out.println("连接可用");
        } catch (Exception e) {
             e.printStackTrace();
             System.out.println("连接打不开!");
        }

        System.out.println(System.currentTimeMillis()-lo);

   }
}

2)编译TestUrl.java

javac TestUrl.java

3)运行TestUrl

java TestUrl

4)若结果如下,则说明证书存在不信任的情况

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1564)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:263)
	at java.net.URL.openStream(URL.java:1045)
	at TestUrl.main(TestUrl.java:13)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
	at sun.security.validator.Validator.validate(Validator.java:260)
	at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
	... 14 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
	at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
	at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392)
	... 20 more
连接打不开!
271

二、JDK将证书导入证书库

1)尽量让接口提供方提供系统的证书,如xxxx.pem、xxxx.crt,将pem或者crt格式的证书转成cer格式

openssl x509 -outform der -in server.pem -out server.cer
openssl x509 -outform der -in server.crt -out server.cer

2)查找jdk证书库

find / -name cacerts

3)导入证书server.cer至jdk证书库

 sudo keytool -import -alias cfcarootca -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/security/cacerts -file server.cer -trustcacerts -storepass changeit

-file后的server.cer为具体的证书存放路径

4)验证是否成功

java TestUrl

5)结果如下便已经能够调用接口

连接可用
351

总结

关键还是证书要正确,笔者曾试过用浏览器中导出的证书,有的好使有的不好使,所以最好还是能让接口的提供方提供系统使用的证书。

这个错误通常意味着服务器之间的API调用发生了证书验证失败的问题。PKIX代表Public Key Infrastructure (X.509),是一种用于数字证书的公钥基础设施。 "PKIX path building failed" 表示证书路径构建失败,意味着服务器无法验证目标服务器的证书链的有效性。 "SunCertPathBuilderException" 是一个异常,表示证书路径构建时遇到了问题。 解决这个问题的一种方法是确保你的服务器信任目标服务器的证书。这可以通过导入或更新根证书来实现。 具体步骤可能因服务器配置而异,但一般需要将目标服务器的根证书添加到你的服务器的受信任存储库中。 你可以参考以下步骤来解决这个问题: 1. 从目标服务器获取证书。可以通过浏览器导出证书或使用命令行工具如openssl来获取。 2. 将证书保存到你的服务器上的某个位置,例如`/path/to/certificate.crt`。 3. 打开你的服务器上的受信任证书存储库。存储库位置可能因操作系统和使用的Java版本而异。 4. 将目标服务器的根证书导入到受信任证书存储库中。可以使用keytool或其他相关工具来执行此操作。例如,使用以下命令导入证书: ``` keytool -import -trustcacerts -file /path/to/certificate.crt -alias certificate_alias -keystore /path/to/truststore.jks ``` 请确保将`/path/to/certificate.crt`替换为你保存证书的实际路径,将`certificate_alias`替换为你选择的别名,并将`/path/to/truststore.jks`替换为你实际的受信任证书存储库路径。 5. 重新启动你的服务器,使其加载更新后的证书存储库。 这样,你的服务器应该能够成功验证目标服务器的证书,并且API调用再报错。请记住,在操作证书方面要小心,确保只信任可靠和受信任证书
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值