2010-10-31 128 views
33

我打电话一些HTTPS的Web服务,它下面的客户端:PKIX路径建设失败:无法找到有效的认证路径要求的目标

import java.io.ByteArrayOutputStream; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.PrintStream; 
import java.net.HttpURLConnection; 
import java.net.URL; 

import javax.net.ssl.HttpsURLConnection; 

/** 
* Handles http and https connections. It sends XML request over http (or https) 
* to SOAP web service and receive the XML reply. 
* 
* @author mhewedy 
* @date 30.10.2010 
*/ 
public class HttpWSXmlClient 
{ 
    private final String ws_url; 
    private byte[] requestData; 

    public HttpWSXmlClient(String wsUrl) 
    { 
     this.ws_url = wsUrl; 
    } 

    public void readRequest(String xmlRequestFilePath) 
    { 
     try 
     { 
      InputStream istream = new FileInputStream(xmlRequestFilePath); 
      byte[] data = stream2Bytes(istream); 
      istream.close(); 
      this.requestData = data; 
     } catch (Exception e) 
     { 
      throw new RuntimeException(e.getMessage()); 
     } 
    } 

    /** 
    * 
    * @param ps 
    *   PrintStream object to send the debugging info to. 
    * @return 
    * @throws IOException 
    */ 
    public byte[] sendAndRecieve(PrintStream ps) throws IOException 
    { 
     if (requestData == null) 
      throw new RuntimeException(
        "the request data didn't initialized yet."); 
     if (ps != null) 
      ps.println("Request:\n" + new String(requestData)); 
     URL url = new URL(ws_url); 
     HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); 
     // or HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
     connection.setDoOutput(true); 
     connection.setRequestProperty("content-type", "text/xml"); 
     connection.connect(); 
     OutputStream os = connection.getOutputStream(); 
     os.write(requestData); 
     InputStream is = connection.getInputStream(); 
     byte[] rply = stream2Bytes(is); 
     if (ps != null) 
      ps.println("Response:\n" + new String(rply)); 
     os.close(); 
     is.close(); 
     connection.disconnect(); 
     return rply; 
    } 

    public byte[] sendAndRecieve() throws IOException 
    { 
     return sendAndRecieve(null); 
    } 

    private byte[] stream2Bytes(InputStream istream) throws IOException 
    { 
     ByteArrayOutputStream outstream = new ByteArrayOutputStream(); 
     int c; 
     while ((c = istream.read()) != -1) 
     { 
      if (c != 0x0A && c != 0x0D) // prevent new line character from being 
      // written 
      { 
       if (c == 0x09) 
        c = 0x20; // prevent tab character from being written, 
       // instead write single space char 
       outstream.write(c); 
      } 
     } 
     byte[] ret = outstream.toByteArray(); 
     outstream.close(); 
     return ret; 
    } 

} 

测试:

public class Test 
{ 
    private static final String WS_URL = "https://some_server/path/to/ws"; 

    public static void main(String[] args) throws Exception 
    { 
     HttpWSXmlClient client = new HttpWSXmlClient(WS_URL); 
     client.readRequest("request.xml"); 
     client.sendAndRecieve(System.out); 
    } 
} 

我得到了以下的输出:

Exception in thread "Main Thread" 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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1591) 
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187) 
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181) 
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1035) 
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:124) 
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:516) 
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:454) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1096) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123) 
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1107) 
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:415) 
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166) 
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:133) 
    at com.se.swstest.HttpWSXmlClient.sendAndRecieve(HttpWSXmlClient.java:63) 
    at com.se.swstest.Test.main(Test.java:11) 
Caused by: 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.validator.PKIXValidator.doBuild(PKIXValidator.java:285) 
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:191) 
    at sun.security.validator.Validator.validate(Validator.java:218) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209) 
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249) 
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1014) 
    ... 12 more 
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174) 
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238) 
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:280) 
    ... 18 more 

我需要将任何证书放在jdk/jre/lib/security? 另外,我有一个xxx_IE.crt和xxx_FX.crt(分别适用于Firefox和IE,并且它们不适用于上述Java客户端,因此我需要为Java客户端指定一个特定证书吗?

谢谢。

+0

这可能会帮助:http://stackoverflow.com/questions/9210514/unable-to-find-valid-certification-path-to-requested-target-error-even-after-c – yegor256 2012-10-31 07:14:06

回答

18

您需要设置证书来打这个URL中使用下面的代码来设置密钥库:。

System.setProperty("javax.net.ssl.trustStore","clientTrustStore.key"); 

System.setProperty("javax.net.ssl.trustStorePassword","qwerty"); 
+0

这实际上工作对我来说,因为我将信任存储设置为我的'whatever.jks'文件,尽管我不确定原因。但是,谢谢。 – EpicPandaForce 2014-10-20 09:48:45

+0

在这里工作得很好..明白我甚至不知道什么信任商店是:/ – aswzen 2016-11-10 05:40:25

+0

信任库不包含密钥,因此命名它.key是毫无意义的。 – EJP 2017-02-04 07:28:30

5

我碰到的这几次,这是由于证书链不完整。如果你正在使用标准的Java信任存储,它可能没有完成验证证书所需的证书链所需的证书您要连接到的SSL站点的名称。

我遇到了一些DigiCert证书的问题,必须自己手动添加中介证书。

+1

我也有一个DigiCert,我猜你遇到了同样的问题。在我的情况下,我无法从浏览器中导出整个证书链,将其全部添加到信任库中。你能分享你的方式吗? – 2014-01-14 03:15:05

+0

你使用什么浏览器?我相信我使用Firefox来做到这一点,尽管我不记得确切的方法。 – Casey 2014-01-14 03:16:08

+0

我之前使用过IE。现在我可以用FireFox导出它,成功添加到信任存储区,但仍然有相同的异常。我会继续尝试。不管怎么说,还是要谢谢你! – 2014-01-14 03:38:49

0

对我来说,我在调用web服务调用时遇到了这个错误,请确保该站点有一个有效的ssl,即检查url侧面的徽标,否则需要将证书添加到受信任的密钥存储区在您的机器上

1

在Mac OS上,我必须使用系统钥匙串访问工具打开服务器的自签名证书,导入它,dobubleclick它,然后选择“始终信任”(即使我在导入器中设置相同)。 在此之前,当然我运行java密钥与-importcert将同一个文件导入cacert存储。

0

我也遇到了这种类型的问题。我正在使用tomcat服务器,然后我把在tomcat背书的文件夹,然后它开始work.And我也取代了JDK1.6 1.7然后它的工作。最后我学习SSL,然后我解决了这种类型的问题。首先,您需要从该服务提供商服务器下载证书。然后您握手成功。 1.Try把批准文件夹中的服务器 接下来方式 2.使用jdk1.7

下一页 3.Try使用SSL

+0

这不回答这个问题。通过认可的文件夹是什么意思? – Lucky 2017-02-17 12:13:39

6

的Java 8解决方案下载有效的证书:我只是有这个问题,通过将远程站点的证书添加到我的Java密钥库来解决此问题。我的解决方案基于solution at the myshittycode blog,它基于previous solution in mykong's blog。这些博客文章解决方案归结为下载一个名为InstallCert的程序,这是一个可从命令行运行以获取证书的Java类。然后继续在Java的密钥库中安装证书。

InstallCert Readme适合我。你只需要运行下面的命令:

  1. javac InstallCert.java
  2. java InstallCert [host]:[port](当你运行该命令输入给定的列表要在列表中添加证书的 - 可能只是)
  3. keytool -exportcert -alias [host]-1 -keystore jssecacerts -storepass changeit -file [host].cer
  4. sudo keytool -importcert -alias [host] -keystore [path to system keystore] -storepass changeit -file [host].cer

如果需要,请参阅参考自述文件的示例。

+0

请注意,系统的密钥库可能位于:'$ JAVA_HOME/jre/lib/security/cacerts'。 – entpnerd 2016-04-13 20:33:53

3

以下是我用于将站点的公共证书安装到系统密钥库中以供使用的解决方案。

下载使用以下命令证书:

UNIX,LINUX,MAC

openssl s_client -connect [host]:[port|443] < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > [host].crt 

窗口

openssl s_client -connect [host]:[port|443] < NUL | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > [host].crt 

这将创建一个CRT,可以是用于导入密钥库。

使用以下命令安装新的证书:

keytool -import -alias "[host]" -keystore [path to keystore] -file [host].crt 

这将允许你从引起异常的网站导入新证书。

+1

许多现代服务器使用SNI;如果是's_client'来获得正确的证书,则添加'-servername $ host'。在java7中,'-importcert'可以处理PEM文件中的无关文本,所以你不需要'sed';在j7中,'keytool -printcert -sslserver $ host [:$ port] -rfc'获取证书链并在PEM中打印(如's_client -showcerts',不带无关文本),如果没有OpenSSL安装例如视窗。 – 2017-10-31 07:55:44

4

我在尝试从Java代码发起SOAP请求时遇到了这种情况。什么工作对我来说是:

  1. 通过点击浏览器的网址,以获取服务器证书:http://docs.bvstools.com/home/ssl-documentation/exporting-certificate-authorities-cas-from-a-website 此连结的所有步骤。一旦你有你的服务器证书获取服务器证书

  2. 按照http://java.globinch.com/enterprise-java/security/pkix-path-building-failed-validation-sun-security-validatorexception/#Valid-Certification-Path-to-Requested-Target

从复制链接的文本,在这种情况下,死链接:

所有你需要做的,解决这个错误是在服务器证书 添加到受信任的Java密钥存储区。首先,您需要从服务器下载 文档。

一旦你在你的硬盘驱动器中有证书,你可以将它导入到 Java信任存储。要将证书导入受信任的Java密钥存储区,您可以使用java'keytool'工具。在命令提示符 导航到JRE bin文件夹,在我的情况下路径是:C:\ Program Files \ Java \ jdk1.7.0_75 \ jre \ bin。然后使用keytool命令,如下所示 将证书导入JRE。

的keytool -import -alias _alias_name_ -keystore .. \ lib \ security中\ cacerts中 -file _path_to_cer_file

它会要求输入密码。默认情况下,密码是“changeit”。如果 密码不同,则可能无法导入 证书。

相关问题