Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SSLHandshakeException:ValidatorException:PKIX路径生成失败:sun.security.provider.certpath.SunCertPathBuilderException:_Java_Spring_Ssl_Spring Boot_Ssl Certificate - Fatal编程技术网

Java SSLHandshakeException:ValidatorException:PKIX路径生成失败:sun.security.provider.certpath.SunCertPathBuilderException:

Java SSLHandshakeException:ValidatorException:PKIX路径生成失败:sun.security.provider.certpath.SunCertPathBuilderException:,java,spring,ssl,spring-boot,ssl-certificate,Java,Spring,Ssl,Spring Boot,Ssl Certificate,我尝试在不进行证书检查的情况下使用https请求本地服务。但我得到了这个机会 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to r

我尝试在不进行证书检查的情况下使用https请求本地服务。但我得到了这个机会

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
以下是代码的一部分:

try {
            RestTemplate restTemplate = new RestTemplate();
            HttpsURLConnection.setDefaultHostnameVerifier(
                    (hostname, session) -> hostname.equals("IPADDRESS"));
            responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
        } catch (HttpClientErrorException e) {
            LOGGER.error(e.toString());
        }

这里怎么了

此问题是由于服务器证书的信任路径不完整造成的:客户端可能不信任服务器证书

通常修复方法是将服务器证书导入客户端信任存储。默认的信任库位于jre/lib/security/cacerts中,但使用自己的密钥库是一种更好的做法

您可以创建一个
SSLSocketFactory
并在连接之前添加到您的连接中,或者使用静态方法应用于所有连接

 HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);
这是一个创建套接字工厂的示例

/* Load the keyStore that includes the server cert as a "trusted" entry. */
KeyStore keyStore = ... 
TrustManagerFactory tmf = 
  TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, tmf.getTrustManagers(), null);
sslFactory = ctx.getSocketFactory();
加载密钥库的示例

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(trustStore, trustStorePassword);
trustStore.close();
还可以使用系统属性配置信任存储

 System.setProperty("javax.net.ssl.trustStore", "pathtoyourjavakeystorefile");
 System.setProperty("javax.net.ssl.trustStorePassword", "password");
创建密钥存储文件的最简单方法是使用GUI工具Portecle。新建密钥库>导入受信任证书


如果要“信任”来自根的所有证书,或者只导入服务器证书,则可以导入链的根证书。对于自签名证书,请直接导入它

Hy

我用这个代码部分解决了这个问题:

private void disableCertificateVerification() {
        TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)                  throws CertificateException {
            }

            @Override
            public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
                    throws CertificateException {
            }
        } };

        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
            HttpsURLConnection.setDefaultHostnameVerifier(
                    (hostname, session) -> hostname.equals("IPADDRESS"));
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            LOGGER.error(e.toString());
        }
    }

在创建RestTemplate之前,我调用了这个函数

服务器正在使用自签名或过期证书自签名证书。修改已安装的JRE从来不是一个好主意-因此这不是通常的修复!创建一个Java密钥库文件,创建一个TrustManager,并使用该密钥库对其进行初始化,这是一种常见的、正确的修复方法……而且您不必导入整个证书链。“只要一个头就行了。”罗伯特,你说得对。推荐的方法应该是使用信任库,而不是覆盖cacerts。我更新answer@EJP,您可以导入根证书或服务器证书,具体取决于您希望“信任”所有CA证书还是仅导入服务器的证书。此外,我将把你的评论包括在answer@EJP+pedrofb:自签名证书是根证书,因此在这种情况下没有区别。对于具有多个证书的“真实”链,Java可以使用沿该链选择的任何证书作为信任锚点。还可以根据需要将默认SSL工厂与sysprops
javax.net.SSL.trustStore{,Password,Type}
一起使用。请参阅javadoc中的JSSE参考指南。禁用TrustManager会使您的客户端接受任何证书。这是令人沮丧的。你应该在信任库中包含受信任的证书我知道,这只是一个测试