0
点赞
收藏
分享

微信扫一扫

服务调用https 接口javax.net.ssl.SSLHandshakeException: PKIX path building fa

服务调用HTTPS接口: PKIX路径构建失败异常

在现代的网络通信中,HTTPS的使用已经非常普遍。与HTTP相比,HTTPS通过使用SSL/TLS协议对通信进行加密,确保数据的安全性和完整性。然而,有时候在通过Java代码调用HTTPS接口时,可能会遇到javax.net.ssl.SSLHandshakeException: PKIX path building failed异常。本文将介绍这个异常的原因和解决方法。

异常原因

PKIX(Public Key Infrastructure X.509)是一种公钥基础设施标准,用于验证证书链的合法性。在与HTTPS服务器建立连接时,Java代码会执行证书链的验证过程。如果服务器的证书链中的任何一个证书无法通过验证,就会抛出javax.net.ssl.SSLHandshakeException: PKIX path building failed异常。

这个异常通常有以下几种原因:

  1. 服务器的证书链中存在过期或无效的证书。
  2. 服务器的证书链中的证书在本地信任库中找不到。
  3. 本地信任库中的证书已过期或失效。

解决方法

针对上述的异常原因,我们可以采取以下几种解决方法。

1. 更新本地信任库

我们可以通过更新本地信任库中的证书,来确保服务器证书链中的证书可以正确地进行验证。

首先,我们需要获取服务器证书链中的证书,可以使用以下代码获得服务器证书的PEM格式字符串:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

public class RetrieveCert {
    public static void main(String[] args) throws IOException, CertificateException {
        String url = "
        URL serverUrl = new URL(url);
        Certificate[] serverCerts = retrieveCertificates(serverUrl);

        // 打印证书信息
        for (Certificate cert : serverCerts) {
            System.out.println(cert.toString());
        }
    }

    private static Certificate[] retrieveCertificates(URL url) throws IOException, CertificateException {
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()))) {
            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                if (inputLine.contains("BEGIN CERTIFICATE") && !inputLine.contains("END CERTIFICATE")) {
                    StringBuilder certBuffer = new StringBuilder();
                    certBuffer.append(inputLine).append("\n");

                    // 读取整个证书
                    while ((inputLine = in.readLine()) != null) {
                        certBuffer.append(inputLine).append("\n");
                        if (inputLine.contains("END CERTIFICATE")) {
                            break;
                        }
                    }

                    // 解析证书
                    Certificate cert = certFactory.generateCertificate(new ByteArrayInputStream(
                            certBuffer.toString().getBytes()));
                    // 添加到证书链中
                    // ...
                }
            }
        }
        // 返回证书链
        // ...
    }
}

在上述代码中,我们通过URL类从HTTPS链接获取服务器返回的数据,并从中提取证书。然后,我们将证书添加到证书链中进行验证。具体的证书添加方式根据不同的请求库和框架而定。

2. 导入服务器证书到本地信任库

如果服务器的证书链中的证书无法通过验证,我们可以将服务器的证书手动导入本地信任库中,以确保Java代码可以正确验证服务器证书。

首先,我们需要获取服务器的证书,可以使用以下命令从HTTPS服务器获取证书:

openssl s_client -showcerts -servername example.com -connect example.com:443 </dev/null

然后,我们将输出的证书保存为一个PEM格式的文件,例如example.crt

接下来,我们可以使用keytool命令将证书导入到本地信任库中:

keytool -import -trustcacerts -alias example -file example.crt -keystore cacerts

cacerts是Java默认的信任库文件,通常位于JDK安装目录的lib/security目录下。

3. 忽略证书验证

在某些情况下,我们可能希望暂时忽略对服务器证书的验证。这通常用于测试或开发环境中

举报

相关推荐

0 条评论