SSLHandshakeException:PKIX 路径构建失败 SunCertPathBuilderException:无法找到请求目标的有效证书路径

Posted

技术标签:

【中文标题】SSLHandshakeException:PKIX 路径构建失败 SunCertPathBuilderException:无法找到请求目标的有效证书路径【英文标题】:SSLHandshakeException: PKIX path building failed SunCertPathBuilderException: unable to find valid certification path to requested target 【发布时间】:2020-11-25 05:58:05 【问题描述】:

我已将 PEM 文件 cert.crt.pem 和 cert.key.pem 复制到文件路径中,并在使用详细信息 url、消息类型、pem 文件和密码为 REST 服务执行以下代码时,出现错误“SSLHandshakeException”。

例外:

连接示例:javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径

代码:

class RestWebServicePEM 

    public static void main(String[] args) 
        String url = "<authenticate_url>";
        String msgType = "application/json";
        String method = "POST";
        String pass = "<password>";
        File certKeyFile = new File("cert.crt.pem");
        File privateKeyFile = new File("cert.key.pem");

       
         HttpsURLConnection con = getSslConnection(url, msgType, method, privateKeyFile, certKeyFile, pass);
         int responseCode = con.getResponseCode();
       
    

    private HttpsURLConnection getSslConnection(String inUrl, String inMsgType, String inMethod,
                                                File privateKeyPem, File certificatePem, String password) 
        HttpsURLConnection con = null;
        SocketFactory sslSocketFactory = createSSLSocketFactory(privateKeyPem, certificatePem, password);
        HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
        try 
            URL url = new URL(inUrl);
            con = (HttpsURLConnection) url.openConnection();
            con.setSSLSocketFactory(sslSocketFactory);
            if (inMethod == "POST") 
                con.setRequestMethod(inMethod);
                con.setDoOutput(true);
            

            con.setInstanceFollowRedirects(true);
            con.setConnectTimeout(30000);
            con.setReadTimeout(30000);

            con.setRequestProperty("Content-Type", inMsgType);

            con.connect();
         catch (Exception e) 
            if (con)
                con.disconnect();
            con = null;
        
        return con;
    

    private SSLSocketFactory createSSLSocketFactory(File privateKeyPem, File certificatePem, String password) throws Exception 
        SSLContext context = SSLContext.getInstance("TLS");
        KeyStore keystore = createKeyStore(privateKeyPem, certificatePem, password);
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(keystore, password.toCharArray());
        KeyManager[] km = kmf.getKeyManagers();
        context.init(km, null, null);
        return context.getSocketFactory();
    

    private KeyStore createKeyStore(File privateKeyPem, File certificatePem, final String password)
            throws Exception, KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException 
        X509Certificate[] cert = createCertificates(certificatePem);
        KeyStore keystore = KeyStore.getInstance("JKS");
        keystore.load(null);

        PrivateKey key = createPrivateKey(privateKeyPem);
        keystore.setKeyEntry(privateKeyPem.getName(), key, password.toCharArray(), cert);
        return keystore;
    

    private PrivateKey createPrivateKey(File privateKeyPem) throws Exception 
        BufferedReader r = new BufferedReader(new FileReader(privateKeyPem));
        String s = r.readLine();

        while (s != null) 
            if (s.contains("BEGIN PRIVATE KEY")) 
                break;
            
            s = r.readLine();
        

        StringBuilder b = new StringBuilder();
        s = "";
        while (s != null) 
            if (s.contains("END PRIVATE KEY")) 
                break;
            
            b.append(s);
            s = r.readLine();
        
        r.close();
        String hexString = b.toString();
        byte[] bytes = DatatypeConverter.parseBase64Binary(hexString);
        return generatePrivateKeyFromDER(bytes);
    

    private X509Certificate[] createCertificates(File certificatePem) throws Exception 
        List<X509Certificate> result = new ArrayList<X509Certificate>();
        BufferedReader r = new BufferedReader(new FileReader(certificatePem));
        String s = r.readLine();
        while (s != null) 
            if (s.contains("BEGIN CERTIFICATE")) 
                break;
            
            s = r.readLine();
        

        StringBuilder b = new StringBuilder();
        while (s != null) 
            if (s.contains("END CERTIFICATE")) 
                String hexString = b.toString();
                final byte[] bytes = DatatypeConverter.parseBase64Binary(hexString);
                X509Certificate cert = generateCertificateFromDER(bytes);
                result.add(cert);
                addMessage("Certificate:"+cert);
                b = new StringBuilder();
             else 
                if (!s.startsWith("----")) 
                    b.append(s);
                
            
            s = r.readLine();
        
        r.close();

        return result.toArray(new X509Certificate[result.size()]);
    

    private RSAPrivateKey generatePrivateKeyFromDER(byte[] keyBytes) throws InvalidKeySpecException, NoSuchAlgorithmException 
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory factory = KeyFactory.getInstance("RSA");
        return (RSAPrivateKey) factory.generatePrivate(spec);
    

    private X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException 
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
    


【问题讨论】:

【参考方案1】:

您可以通过将证书添加到 Java 密钥库来解决此问题。

    下载证书。

    转到路径 ...jre\lib\security。

    把证书放在这里。

    运行key tool命令(管理员模式)如果要求输入密码(changeit)

    keytool -keystore cacerts -importcert -alias "你的别名" -file certificare name.cer

5.现在您可以删除 SSL 验证码了。

【讨论】:

以上是关于SSLHandshakeException:PKIX 路径构建失败 SunCertPathBuilderException:无法找到请求目标的有效证书路径的主要内容,如果未能解决你的问题,请参考以下文章

Scala:如何忽略“SSLHandshakeException”

文件下载 SSLHandshakeException

SSLHandshakeException 无法验证用户身份

SSLHandshakeException:不存在主题替代名称

服务帐户引发 - SSLHandshakeException

Jmeter中的SSLHandshakeException错误