"PKIX路径构建失败" 和 "无法找到请求目标的有效认证路径"

892

我正在尝试在我的Java项目中使用twitter4j库获取推文,在底层使用的是java.net.HttpURLConnection(如堆栈跟踪所示)。在第一次运行时,我遇到了关于证书sun.security.validator.ValidatorExceptionsun.security.provider.certpath.SunCertPathBuilderException的错误。然后我通过以下方式添加了Twitter证书:

C:\Program Files\Java\jdk1.7.0_45\jre\lib\security>keytool -importcert -trustcacerts -file PathToCert -alias ca_alias -keystore "C:\Program Files\Java\jdk1.7.0_45\jre\lib\security\cacerts"

但是没有成功。这里是获取推文的过程:

public static void main(String[] args) throws TwitterException {
    ConfigurationBuilder cb = new ConfigurationBuilder();
    cb.setDebugEnabled(true)
        .setOAuthConsumerKey("myConsumerKey")
        .setOAuthConsumerSecret("myConsumerSecret")
        .setOAuthAccessToken("myAccessToken")
        .setOAuthAccessTokenSecret("myAccessTokenSecret");
    
    TwitterFactory tf = new TwitterFactory(cb.build());
    Twitter twitter = tf.getInstance();
    
    try {
        Query query = new Query("iphone");
        QueryResult result;
        result = twitter.search(query);
        System.out.println("Total amount of tweets: " + result.getTweets().size());
        List<Status> tweets = result.getTweets();
        
        for (Status tweet : tweets) {
            System.out.println("@" + tweet.getUser().getScreenName() + " : " + tweet.getText());
        }
    } catch (TwitterException te) {
        te.printStackTrace();
        System.out.println("Failed to search tweets: " + te.getMessage());
    }

这里是错误:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Relevant discussions can be found on the Internet at:
    http://www.google.co.jp/search?q=d35baff5 or
    http://www.google.co.jp/search?q=1446302e
TwitterException{exceptionCode=[d35baff5-1446302e 43208640-747fd158 43208640-747fd158 43208640-747fd158], statusCode=-1, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=3.0.5}
    at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:177)
    at twitter4j.internal.http.HttpClientWrapper.request(HttpClientWrapper.java:61)
    at twitter4j.internal.http.HttpClientWrapper.get(HttpClientWrapper.java:81)
    at twitter4j.TwitterImpl.get(TwitterImpl.java:1929)
    at twitter4j.TwitterImpl.search(TwitterImpl.java:306)
    at jku.cc.servlets.TweetsAnalyzer.main(TweetsAnalyzer.java:38)
Caused by: 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(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
    at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
    at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
    at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
    at sun.security.ssl.Handshaker.processLoop(Unknown Source)
    at sun.security.ssl.Handshaker.process_record(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at java.net.HttpURLConnection.getResponseCode(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
    at twitter4j.internal.http.HttpResponseImpl.<init>(HttpResponseImpl.java:34)
    at twitter4j.internal.http.HttpClientImpl.request(HttpClientImpl.java:141)
    ... 5 more
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(Unknown Source)
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    ... 20 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 26 more
Failed to search tweets: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

11
你好,请检查下面的网址。我相信这些将对你有所帮助。http://www.java-samples.com/showtutorial.php?tutorialid=210 https://confluence.atlassian.com/display/JIRAKB/Unable+to+Connect+to+SSL+Services+due+to+PKIX+Path+Building+Failed+sun.security.provider.certpath.SunCertPathBuilderException。你需要将你的SSL证书添加到Java信任库证书中(路径:jre/lib/security/cacerts)。 - sus007
4
我刚刚使用了这段 Java 代码,对于 https,请不要忘记将端口指定为 443。 Java 代码位于 https://github.com/escline/InstallCert/blob/master/InstallCert.java它将使用您的 CACERTS 文件,并将添加所有那些以及您输入的 URL 的当前证书。 在我的情况下,我将值硬编码为 host="mywebservice.uat.xyz.com"; port=443; passphrase="changeit".toCharArray();然后,程序会创建一个名为“jssecacerts”的新文件,其中将包含所有内容。将其重命名为“cacerts”并使用此文件。您就可以开始了。 - Reddymails
我只是将HTTPS替换为HTTP,它就能正常工作了。也许我的评论对某人有用。 - Oleksandr
当运行mvn时,添加此参数对我有帮助,因为它由于某种原因未使用JAVA_HOME中的默认Java信任存储:-"Djavax.net.ssl.trustStore"="C:\path\to\your\cacerts" - ADJenks
显示剩余2条评论
60个回答

14

经过半天的努力,我找到了另一种解决此问题的方法。 我在MAC 10.15.5(Catalina)中成功解决了此问题。按照以下步骤进行操作。

  • 当我们在公司代理后面运行时,出现此问题,在我的情况下是Zscaler。
  • 打开钥匙串访问,导出CA证书。(选择CA证书,文件->导出项目并使用所需名称保存)
  • 从Java文件夹中复制现有cacerts的路径 (/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/security/cacerts)
  • 打开终端并导航到Keytool文件夹(/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/bin)
  • 运行以下命令。
  • Keytool -importcert - file (从keychainaccess导出的证书路径) -alias(自定义名称) -keystore (Java文件夹中现有cacerts的路径)
  • sudo Keytool -importcert -file /Users/Desktop/RootCA.cer -alias demo -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/jre/lib/security/cacerts
  • 它会要求输入密码,请输入:changeit
  • 它会要求确认,请输入:yes

完成所有步骤后,退出eclipse和终端,开始一个新的会话。


你是如何在钥匙串访问中获取CA证书的?我的钥匙串访问中没有任何证书。 - linuxNoob

13

问题背景:

当我尝试在项目中运行"mvn clean install"命令或通过Netbeans IDE的"Clean and Build"选项时,出现以下错误。此问题是由于在通过NET beans IDE / 命令提示符下载时证书不可用,但可以通过浏览器下载文件。

错误信息:

Caused by: org.eclipse.aether.transfer.ArtifactTransferException: Could not transfer artifact com.java.project:product:jar:1.0.32 from/to repo-local (https://url/local-repo): sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target  

解决方案:

1. 下载相关网址的证书:

  • 以管理员身份启动IE浏览器(否则,我们将无法下载证书)
  • 在IE中输入网址 -> https://url/local-repo (在我的情况下,此网址有一个不受信任的证书enter image description here。)
  • 点击“证书错误” -> 查看证书来下载证书
  • 选择详细信息标签 -> 复制到文件 -> 下一步 -> 选择“DER编码二进制X.509(.CER)”
  • 将证书保存到某个位置,例如: c:/user/sheldon/desktop/product.cer
  • 恭喜你成功的下载了该网站的证书

2. 安装密钥库以解决问题。

  • 运行keytool命令将下载的密钥库附加到现有的证书文件中。
  • 命令:位于jdk(JAVA_HOME)的bin文件夹中的以下命令。

C:\Program Files\Java\jdk1.8.0_141\jre\bin>keytool -importcert -file "C:/user/sheldon/desktop/product.cer" -alias product -keystore "C:/Program Files/Java/jdk1.8.0_141/jre/lib/security/cacerts".

  • 会提示您输入密码。 输入密钥库密码:输入“changeit”并再次输入“Trust this certificate? [no]:”,输入“yes”

示例命令行命令/输出:

keytool -importcert -file "C:/Users/sheldon/Desktop/product.cer" -alias product -keystore "C:/Program iles/Java/jdk1.8.0_141/jre/lib/security/cacerts"
Enter keystore password:
Trust this certificate? [no]:  yes
Certificate was added to keystore
  • 恭喜!现在你应该已经解决了在Netbeans IDE中出现的“PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException”错误。

嗨,我按照所有步骤操作了,但是没有成功 :( - ManishNegi
除了cacerts之外,您在路径中是否有其他证书?如果有其他证书,请尝试将其添加到该证书中。 - Barani r
谢谢@Barani r,是我的错误,我正在从jre执行命令并在我的eclipse中使用JDK。 - ManishNegi
无法下载证书,但是在以管理员身份运行后,就可以正常工作了。 - Another coder
@Baranir,我特意登录了一下(不记得我的主账户是通过Facebook、Google还是SO链接的),只是为了点赞这个答案。起初它没有起作用,但后来发现我漏掉了-keystore参数。大家,请不要省略-keystore参数。否则,你会拔掉头上剩下的几根头发。开玩笑的,对于一个扎实的答案,点赞+1。 - Kemuel Sanchez

13

以下是我的解决方案及相关问题的故事:

我已经尝试了上面提供的所有解决方案(长达3天),但都没有解决我的问题。

我已经失去了所有的希望。

由于我在代理后面,所以我联系了我的安全团队,他们告诉我他们最近更新了他们的安全策略。

后来,他们发布了一个包含所有证书的新“cacerts”文件。

我删除了位于%JAVA_HOME%/jre/lib/security中的cacerts文件,并解决了我的问题。

所以如果你也遇到这个问题,可能是你的网络团队也像我一样出现了类似的问题。


11
我们之所以会遇到上述错误,是因为JDK捆绑了许多受信任的证书颁发机构(CA)证书到一个名为“cacerts”的文件中,但这个文件对于我们的自签名证书一无所知。换句话说,cacerts文件没有导入我们的自签名证书,因此不将其视为可信实体,从而导致上述错误。 如何修复上述错误 要解决上述错误,我们只需要将自签名证书导入cacerts文件即可。
首先,找到cacerts文件。我们需要找出JDK的位置。如果您正在通过Eclipse或IntelliJ Idea等IDE之一运行应用程序,请转到项目设置并找出JDK位置。例如,在Mac OS上,cacerts文件的典型位置为/Library/Java/JavaVirtualMachines/{{JDK_version}}/Contents/Home/jre/lib/security,而在Windows机器上,则在{{Installation_directory}}/{{JDK_version}}/jre/lib/security下。
一旦您找到了cacerts文件,现在我们需要将自签名证书导入到该cacerts文件中。如果您不知道如何正确生成自签名证书,请查看上一篇文章。
如果您没有证书文件(.crt),而只有一个.jks文件,则可以使用以下命令生成.crt文件。如果您已经有了.crt/.pem文件,则可以忽略以下命令。
##从密钥库(.jks文件)生成证书####
keytool -export -keystore keystore.jks -alias selfsigned -file selfsigned.crt

上述步骤将生成一个名为selfsigned.crt的文件。现在将证书导入到cacerts中。
keytool -importcert -file selfsigned.crt -alias selfsigned -keystore {{cacerts path}}

例如

keytool -importcert -file selfsigned.nextgen.crt -alias selfsigned.nextgen -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts

这就是全部,重新启动您的应用程序,它应该可以正常工作。如果仍然无法正常工作并出现SSL握手异常,则可能意味着您正在使用与证书中注册的不同域。
链接详细解释和逐步解决方案在此处。

你能详细说明一下如何解决这个问题吗?如果仍然无法正常工作并出现SSL握手异常。这可能意味着您正在使用与证书中注册的域不同的域。 - Dorjee Dhondup

8

问题在于,你的Eclipse无法连接它实际上正在尝试连接的网站。 我遇到过类似的问题,下面给出的解决方案对我有效。

  1. 关闭任何第三方互联网安全应用程序,例如Zscaler。
  2. 有时还需要断开VPN连接。

谢谢。


7

简单解决此异常的步骤(我是在Java 11上进行的):

  • 首先需要下载您试图调用的目标域的公共SSL证书文件,具体操作如下:
  • 在Chrome中打开目标域的网站(例如:https://amazonservice.domain.com
  • 点击浏览器中URL之前的小锁图标
  • 点击“查看证书”
  • 现在点击如下所示的“证书有效”
  • enter image description here
  • 现在会出现一个新的弹出窗口,如下所示: Go
  • 在弹出窗口中打开“详细信息”选项卡
  • 选择顶部的RootCert
  • 点击“导出”并将.cer文件保存到您的系统目录中

现在您已经拥有了您在Java应用程序中试图调用的目标域的公共密钥库,现在我们需要将该密钥库导入到您的jre中。为此,请转到$JAVA_HOME/bin目录并运行以下命令:

./keytool -importcert -alias someAliasName -keystore {JAVA_HOME}/lib/security/cacerts -file {PathToDownloads}/certificateFileName.cer

在询问您密码时,请输入密码(如果您知道),证书的默认密码是changeit

参考资料

  1. https://confluence.atlassian.com/kb/how-to-import-a-public-ssl-certificate-into-a-jvm-867025849.html
  2. https://confluence.atlassian.com/kb/unable-to-connect-to-ssl-services-due-to-pkix-path-building-failed-error-779355358.html

7
我曾遇到同样的问题,下面是解决问题的简单步骤:
1)从谷歌下载InstallCert.java
2)使用“javac InstallCert.java”命令进行编译。
3)使用“java InstallCert.java”命令运行InstallCert.java,并输入主机名和https端口号。在询问输入时,请输入“1”。它将把“localhost”添加为受信任的密钥库,并生成一个名为“jssecacerts”的文件。
java InstallCert localhost:443
4)复制jssecacerts文件到$JAVA_HOME/jre/lib/security文件夹中。
解决问题的主要来源在此:https://ankurjain26.blogspot.in/2017/11/javaxnetsslsslhandshakeexception.html

链接已经失效。但是对于我来说它是可以工作的。 - Ajay Takur

5

添加 cacerts 对我没有起作用。 通过使用标记 -Djavax.net.debug=all 启用日志后,才知道 Java 正在从 jssecacerts 读取。

最终通过导入到 jssecacerts 中解决了问题。


4
这里缺少的解释是,如果存在jssecacerts,Java将使用它,否则使用cacerts - user207421

4

如果您仍然遇到这个错误

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid 
certification path to requested target

在执行下面的命令并重新启动Java进程后:

keytool -import -alias certificatealias -keystore C:\Program Files\Java\jre1.8.0_151\lib\security\cacerts -file certificate.cer

那么问题可能出在JDK上。试着从可信的提供者安装JDK。 一旦你从可信的提供者重新安装了JDK,你就不会再遇到这个问题了。


你肯定需要将你的crt重命名为cer。 - scavenger

4

在尝试通过Eclipse更新站点安装Cucumber-Eclipse插件时,我遇到了这个问题。我收到了相同的SunCertPathBuilderException错误:

Unable to read repository at http://cucumber.io/cucumber-eclipse/update-site/content.xml.
    Unable to read repository at http://cucumber.io/cucumber-eclipse/update-site/content.xml.
    sun.security.validator.ValidatorException: PKIX path building failed: 
   sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

虽然其他答案对于这个问题的情况是适当和有帮助的,但对于我的问题来说仍然是无用和误导的。在我的情况下,问题是他们提供的更新站点的URL是:

https://cucumber.io/cucumber-eclipse/update-site

然而,当通过浏览器导航到它时,它会重定向到(请注意添加的“.github”):

http://cucumber.github.io/cucumber-eclipse/update-site/

因此,解决方法是在Eclipse中添加更新站点时,使用重定向版本的更新站点URL。

3
你确定你回答的是正确的问题吗?原始问题中没有提到黄瓜... - Done Data Solutions
1
我感觉我是。我遇到了相同的SunCertPathBuilderException错误,并在寻找解决方法时发现了这个问题以及这个。然而,它们都没有适合我情况的解决方案。我并不是试图回答如何将Cucumber-Eclipse插件站点添加到eclipse的具体问题。我想提供我所面临的问题(URL重定向)的背景,并解释它是如何被解决的。 - royfripple
1
我更新了我的答案,明确表明我遇到了同样的错误,并指出根本原因和解决方案是不同的。我认为这是有效的,因为其他人在搜索相同的错误时可能会找到这个问题。如果您认为这有意义,请考虑更改您的投票。 - royfripple
谢谢。这让事情更清晰了,我取消了我的负评。 - Done Data Solutions
不用谢!也感谢您抽出时间再次审查它。 - royfripple

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接