【问题标题】:PKIX path building failed: SunCertPathBuilderException: unable to find valid certification path to requestedPKIX 路径构建失败:SunCertPathBuilderException:无法找到请求的有效证书路径
【发布时间】:2021-04-14 07:30:56
【问题描述】:

我正在使用 eclipse,在尝试执行此功能时遇到错误。

我想连同证书和密钥一起发送一个 GET 请求。我可以下载任何格式的证书,所以这不是问题。我知道我需要将此添加到 java keystone 但在尝试了各种建议后我仍然无法解决此问题。

   public String sendGET(String GET_URL, String authStringEnc) throws IOException {
            try {
                KeyStore ks = KeyStore.getInstance("JKS");
                FileInputStream fis = new FileInputStream("src/com/resources/ece-cyberark-cert.jks");
                ks.load(fis, "5<@7wBj[Ht()~GRf".toCharArray());
                KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
                kmf.init(ks, "5<@7wBj[Ht()~GRf".toCharArray());
                SSLContext sc = SSLContext.getInstance("TLS");
                sc.init(kmf.getKeyManagers(), null, null);
                URL obj = new URL(GET_URL);
                HttpURLConnection con = (HttpURLConnection) obj.openConnection();
                if (con instanceof HttpsURLConnection) {
                    ((HttpsURLConnection)con)
                         .setSSLSocketFactory(sc.getSocketFactory());
                }
                con.setRequestMethod("GET");
                con.setRequestProperty("User-Agent", USER_AGENT);
                con.setRequestProperty("Authorization", "Basic " + authStringEnc);      
                con.setRequestProperty("Content-Type", "application/json");
                
                int responseCode = con.getResponseCode();
                System.out.println("GET Response Code :: " + responseCode + " :: " + GET_URL);
                if (responseCode == HttpURLConnection.HTTP_OK) { // success
                    BufferedReader in = new BufferedReader(new InputStreamReader(
                            con.getInputStream()));
                    String inputLine;
                    StringBuffer response = new StringBuffer();
    
                    while ((inputLine = in.readLine()) != null) {
                        response.append(inputLine);
                    }
                    in.close();
                    con.disconnect();
                    // print result
                    return response.toString();
                } else {
                    // return failed requests response code
                    return "GET request not worked :: GET Response Code :: " + responseCode + " ::  + GET_URL";
                }
            } catch (Exception e) {
                e.printStackTrace();
                return "Exceptionn";
            }
            
            
    
        }

以下是错误-

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:1946)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)

【问题讨论】:

  • 您正在使用密钥管理器初始化您的 SSL 上下文,而不是使用信任管理器。如果您需要向服务器验证您(客户端)的身份,密钥管理器很有用。但是在这里,问题出现在之前,当您(客户端)尝试对服务器进行身份验证时(您的异常表明)。尝试将服务器的证书加载为用于构建 TrustManager 的密钥库中的受信任条目(SSLContext#init() 的第二个参数)。
  • 即使在使用 sudo key tool import 添加证书后,我仍然遇到同样的错误

标签: java java-8 keystore


【解决方案1】:

密钥管理器用于向 HTTP 服务器验证您(HTTP 客户端)的身份。但首先,信任管理器用于对服务器进行身份验证。如果服务器的证书在运行时的默认“信任锚”下不受信任,则需要明确提供正确的根证书。

KeyStore trusted = ...; /* Initialize a trust store containing the non-standard CA. */
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(trusted);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
...

如果您不打算使用 TLS 客户端身份验证,则应删除所有与 KeyManager 相关的初始化。

【讨论】:

    最近更新 更多