2016-06-19 82 views
0

我尝试使用https请求本地服务而无需进行证书检查。但我得到了这个答案。SSLHandshakeException:ValidatorException:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:

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()); 
     } 

这里有什么问题?

+0

服务器正在使用自签名或过期证书 –

+0

自签名证书 – emoleumassi

回答

1

海兰,

我这个代码部分解决它:

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之前,我调用该函数。

+0

禁用TrustManager会使您的客户接受任何证书。这是不鼓励的。我应该在信任库 – pedrofb

+0

中包含可信证书,我知道,它只是一个测试 – emoleumassi

0

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

通常,修复方法是将服务器证书导入到客户端信任库中。默认的trustStore是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(); 

实施例加载密钥库

信任存储还可以使用系统属性

System.setProperty("javax.net.ssl.trustStore", "pathtoyourjavakeystorefile"); 
System.setProperty("javax.net.ssl.trustStorePassword", "password"); 

创建密钥存储文件的最简单方法是配置使用GUI工具Portecle。 新KeyStore>导入可信证书

如果您要'信任'来自根的所有证书或只导入服务器证书,您可以导入该链的根证书。对于自签名证书,导入直接

+1

我不同意。修改已安装的JRE绝不是一个好主意 - 因此这不是通常的解决方法!创建一个Java KeyStore文件,创建一个TrustManager并使用该KeyStore对其进行初始化,该KeyStore是通常和正确的修复程序... – Robert

+0

而且您不必导入整个证书链。只是它的头会做。 – EJP

+0

@罗伯特,你是对的。推荐的方式应该是使用您的信任库,而不是覆盖cacerts。我更新了答案 – pedrofb

相关问题