Java “PKIX 路径构建失败”和“无法找到到请求目标的有效认证路径”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21076179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"PKIX path building failed" and "unable to find valid certification path to requested target"
提问by Dozent
I'm trying to get tweets using twitter4jlibrary for my java project. On my first run I got an error about certificate sun.security.validator.ValidatorException
and sun.security.provider.certpath.SunCertPathBuilderException
. Then I added twitter certificate by:
我正在尝试使用twitter4j库为我的 java 项目获取推文。在我第一次运行时,我遇到了关于证书sun.security.validator.ValidatorException
和sun.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"
But without success. Here is the procedure to get tweets:
但没有成功。以下是获取推文的过程:
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());
}
And here is the error:
这是错误:
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
采纳答案by MagGGG
- Go to URL in your browser:
- firefox - click on HTTPS certificate chain (the lock icon right next to URL address). Click
"more info" > "security" > "show certificate" > "details" > "export.."
. Pickup the name and choose file type example.cer - chrome - click on site icon left to address in address bar, select "Certificate" -> "Details" -> "Export" and save in format "Der-encoded binary, single certificate".
- firefox - click on HTTPS certificate chain (the lock icon right next to URL address). Click
Now you have file with keystore and you have to add it to your JVM. Determine location of cacerts files, eg.
C:\Program Files (x86)\Java\jre1.6.0_22\lib\security\cacerts.
Next import the
example.cer
file into cacerts in command line:
- 在浏览器中访问 URL:
- firefox - 单击 HTTPS 证书链(URL 地址旁边的锁图标)。单击
"more info" > "security" > "show certificate" > "details" > "export.."
。选取名称并选择文件类型 example.cer - chrome - 单击地址栏中的左侧站点图标,选择“证书”->“详细信息”->“导出”并以“Der-encoded binary, single certificate”格式保存。
- firefox - 单击 HTTPS 证书链(URL 地址旁边的锁图标)。单击
现在您有了带有密钥库的文件,您必须将其添加到您的 JVM 中。确定 cacerts 文件的位置,例如。
C:\Program Files (x86)\Java\jre1.6.0_22\lib\security\cacerts.
接下来
example.cer
在命令行中将文件导入 cacerts:
keytool -import -alias example -keystore C:\Program Files (x86)\Java\jre1.6.0_22\lib\security\cacerts -file example.cer
keytool -import -alias example -keystore C:\Program Files (x86)\Java\jre1.6.0_22\lib\security\cacerts -file example.cer
You will be asked for password which default is changeit
你会被要求输入密码,默认是 changeit
Restart your JVM/PC.
重新启动您的 JVM/PC。
source: http://magicmonster.com/kb/prg/java/ssl/pkix_path_building_failed.html
来源:http: //magicmonster.com/kb/prg/java/ssl/pkix_path_building_failed.html
回答by ketan
Here normally this kind of exception occurs when there is mismatch in the PATH of trusted certificate. Check the configuration or path where this server certificate is required for secured communication.
通常,当受信任证书的路径不匹配时,会发生这种异常。检查安全通信需要此服务器证书的配置或路径。
回答by Jeremy Goodell
After many hours trying to build cert files to get my Java 6 installation working with the new twitter cert's, I finally stumbled onto an incredibly simple solution buried in a comment in one of the message boards. Just copy the cacerts file from a Java 7 installation and overwrite the one in your Java 6 installation. Probably best to make a backup of the cacerts file first, but then you just copy the new one in and BOOM! it just works.
在尝试构建证书文件以使我的 Java 6 安装与新的 twitter 证书一起工作数小时后,我终于偶然发现了一个非常简单的解决方案,该解决方案隐藏在其中一个留言板的评论中。只需从 Java 7 安装中复制 cacerts 文件并覆盖 Java 6 安装中的文件。可能最好先备份 cacerts 文件,然后您只需将新文件复制到 BOOM!它只是有效。
Note that I actually copied a Windows cacerts file onto a Linux installation and it worked just fine.
请注意,我实际上将 Windows cacerts 文件复制到了 Linux 安装中,并且运行良好。
The file is located in jre/lib/security/cacerts
in both the old and new Java jdk installations.
该文件位于jre/lib/security/cacerts
新旧 Java jdk 安装中。
Hope this saves someone else hours of aggravation.
希望这可以为其他人节省数小时的恶化时间。
回答by will824
I have stumbled upon this issue which took many hours of research to fix, specially with auto-generated certificates, which unlike Official ones, are quite tricky and Java does not like them that much.
我偶然发现了这个问题,需要花费数小时的研究才能解决,特别是使用自动生成的证书,与官方证书不同,它非常棘手,Java 不太喜欢它们。
Please check the following link: Solve Problem with certificates in Java
请查看以下链接:用 Java 解决证书问题
Basically you have to add the certificate from the server to the Java Home certs.
基本上,您必须将来自服务器的证书添加到 Java Home 证书中。
- Generate or Get your certificate and configure Tomcat to use it in Servers.xml
- Download the Java source code of the class
InstallCert
and execute it while the server is running, providing the following argumentsserver[:port]
. No password is needed, as the original password works for the Java certs ("changeit"). - The Program will connect to the server and Java will throw an exception, it will analyze the certificate provided by the server and allow you to create a
jssecerts
file inside the directory where you executed the Program (If executed from Eclipse then make sure you configure the Work directory inRun -> Configurations
). - Manually copy that file to
$JAVA_HOME/jre/lib/security
- 生成或获取您的证书并配置 Tomcat 以在 Servers.xml 中使用它
- 下载该类的 Java 源代码
InstallCert
并在服务器运行时执行它,提供以下参数server[:port]
。不需要密码,因为原始密码适用于 Java 证书(“changeit”)。 - 该程序将连接到服务器,Java 将抛出异常,它将分析服务器提供的证书并允许您
jssecerts
在执行程序的目录中创建一个文件(如果从 Eclipse 执行,请确保您配置了 Work中的目录Run -> Configurations
)。 - 手动将该文件复制到
$JAVA_HOME/jre/lib/security
After following these steps, the connections with the certificate will not generate exceptions anymore within Java.
执行这些步骤后,与证书的连接将不再在 Java 中生成异常。
The following source code is important and it disappeared from (Sun) Oracle blogs, the only page I found it was on the link provided, therefore I am attaching it in the answer for any reference.
以下源代码很重要,它从(Sun)Oracle 博客中消失了,这是我在提供的链接上找到的唯一页面,因此我将其附在答案中以供参考。
/*
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Originally from:
* http://blogs.sun.com/andreas/resource/InstallCert.java
* Use:
* java InstallCert hostname
* Example:
*% java InstallCert ecc.fedora.redhat.com
*/
import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* Class used to add the server's certificate to the KeyStore
* with your trusted certificates.
*/
public class InstallCert {
public static void main(String[] args) throws Exception {
String host;
int port;
char[] passphrase;
if ((args.length == 1) || (args.length == 2)) {
String[] c = args[0].split(":");
host = c[0];
port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
String p = (args.length == 1) ? "changeit" : args[1];
passphrase = p.toCharArray();
} else {
System.out.println("Usage: java InstallCert [:port] [passphrase]");
return;
}
File file = new File("jssecacerts");
if (file.isFile() == false) {
char SEP = File.separatorChar;
File dir = new File(System.getProperty("java.home") + SEP
+ "lib" + SEP + "security");
file = new File(dir, "jssecacerts");
if (file.isFile() == false) {
file = new File(dir, "cacerts");
}
}
System.out.println("Loading KeyStore " + file + "...");
InputStream in = new FileInputStream(file);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, passphrase);
in.close();
SSLContext context = SSLContext.getInstance("TLS");
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
context.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory factory = context.getSocketFactory();
System.out.println("Opening connection to " + host + ":" + port + "...");
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.setSoTimeout(10000);
try {
System.out.println("Starting SSL handshake...");
socket.startHandshake();
socket.close();
System.out.println();
System.out.println("No errors, certificate is already trusted");
} catch (SSLException e) {
System.out.println();
e.printStackTrace(System.out);
}
X509Certificate[] chain = tm.chain;
if (chain == null) {
System.out.println("Could not obtain server certificate chain");
return;
}
BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in));
System.out.println();
System.out.println("Server sent " + chain.length + " certificate(s):");
System.out.println();
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = chain[i];
System.out.println
(" " + (i + 1) + " Subject " + cert.getSubjectDN());
System.out.println(" Issuer " + cert.getIssuerDN());
sha1.update(cert.getEncoded());
System.out.println(" sha1 " + toHexString(sha1.digest()));
md5.update(cert.getEncoded());
System.out.println(" md5 " + toHexString(md5.digest()));
System.out.println();
}
System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
String line = reader.readLine().trim();
int k;
try {
k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
} catch (NumberFormatException e) {
System.out.println("KeyStore not changed");
return;
}
X509Certificate cert = chain[k];
String alias = host + "-" + (k + 1);
ks.setCertificateEntry(alias, cert);
OutputStream out = new FileOutputStream("jssecacerts");
ks.store(out, passphrase);
out.close();
System.out.println();
System.out.println(cert);
System.out.println();
System.out.println
("Added certificate to keystore 'jssecacerts' using alias '"
+ alias + "'");
}
private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int b : bytes) {
b &= 0xff;
sb.append(HEXDIGITS[b >> 4]);
sb.append(HEXDIGITS[b & 15]);
sb.append(' ');
}
return sb.toString();
}
private static class SavingTrustManager implements X509TrustManager {
private final X509TrustManager tm;
private X509Certificate[] chain;
SavingTrustManager(X509TrustManager tm) {
this.tm = tm;
}
public X509Certificate[] getAcceptedIssuers() {
throw new UnsupportedOperationException();
}
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
throw new UnsupportedOperationException();
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
this.chain = chain;
tm.checkServerTrusted(chain, authType);
}
}
}
回答by gorums
-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true
It is used for jump the certificate validation.
它用于跳转证书验证。
WarningOnly use for development purposes for this is unsecure!
警告仅用于开发目的是不安全的!
回答by user1379218
i have the same problem on ubuntu 15.10. Please try download plugin locally e.g. https://github.com/lmenezes/elasticsearch-kopf/archive/master.zipand install with this command:
我在 ubuntu 15.10 上有同样的问题。请尝试在本地下载插件,例如https://github.com/lmenezes/elasticsearch-kopf/archive/master.zip并使用以下命令安装:
sudo /usr/share/elasticsearch/bin/plugin install file:/home/dev/Downloads/elasticsearch-kopf-master.zip
Path maybe different depending on your environment.
路径可能因您的环境而异。
Regards.
问候。
回答by Atihska
For me, certificate error popped up because I had fiddler running in background and that messes up with certificate. It acts as a proxy so close that and restart eclipse.
对我来说,出现证书错误是因为我在后台运行了 fiddler,这弄乱了证书。它充当代理,如此接近并重新启动 eclipse。
回答by Mike Mitterer
MY UI approach:
我的用户界面方法:
- Download keystore explorer from here
- Open $JAVA_HOME/jre/lib/security/cacerts
- enter PW: changeit (Can be changeme on Mac)
- Import your .crt file
- 从这里下载密钥库资源管理器
- 打开 $JAVA_HOME/jre/lib/security/cacerts
- 输入密码:changeit(Mac上可以是changeme)
- 导入您的 .crt 文件
CMD-Line:
CMD-行:
keytool -importcert -file jetty.crt -alias jetty -keystore $JAVA_HOME/jre/lib/security/cacerts
- enter PW:
changeit
(Can be changeme on Mac)
keytool -importcert -file jetty.crt -alias jetty -keystore $JAVA_HOME/jre/lib/security/cacerts
- 输入密码:(
changeit
在Mac上可以changeme)
回答by M. F.
I had a slightly different situation, when both JDK and JRE 1.8.0_112 were present on my system.
我的情况略有不同,当我的系统上同时存在 JDK 和 JRE 1.8.0_112 时。
I imported the new CA certificates into [JDK_FOLDER]\jre\lib\security\cacerts
using the already known command:
我[JDK_FOLDER]\jre\lib\security\cacerts
使用已知的命令导入了新的 CA 证书:
keytool -import -trustcacerts -keystore cacerts -alias <new_ca_alias> -file <path_to_ca_cert_file>
Still, I kept getting the same PKIX path building failederror.
尽管如此,我还是不断收到相同的PKIX 路径构建失败错误。
I added debug information to the java CLI, by using java -Djavax.net.debug=all ... > debug.log
. In the debug.log file, the line that begins with trustStore is:actually pointed to the cacerts store found in [JRE_FOLDER]\lib\security\cacerts
.
我使用java -Djavax.net.debug=all ... > debug.log
. 在 debug.log 文件中,以trustStore开头的行是:实际上指向在 中找到的 cacerts 存储[JRE_FOLDER]\lib\security\cacerts
。
In my case the solution was to copy the cacerts file used by JDK (which had the new CAs added) over the one used by the JRE and that fixed the issue.
在我的情况下,解决方案是将 JDK 使用的 cacerts 文件(添加了新的 CA)复制到 JRE 使用的文件上,从而解决了问题。
回答by Sneha Shejwal
I wanted to import certificate for smtp.gmail.com
我想为 smtp.gmail.com 导入证书
Only solution worked for me is 1. Enter command to view this certificate
唯一对我有用的解决方案是 1. 输入命令查看此证书
D:\openssl\bin\openssl.exe s_client -connect smtp.gmail.com:465
D:\openssl\bin\openssl.exe s_client -connect smtp.gmail.com:465
Copy and save the lines between "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" into a file, gmail.cer
Run
keytool -import -alias smtp.gmail.com -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file C:\Users\Admin\Desktop\gmail.cer
Enter password chageit
Click yes to import the certificate
Restart java
将“-----BEGIN CERTIFICATE-----”和“-----END CERTIFICATE-----”之间的行复制并保存到文件gmail.cer中
跑
keytool -import -alias smtp.gmail.com -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file C:\Users\Admin\Desktop\gmail.cer
输入密码 chageit
单击是导入证书
重启java
now run the command and you are good to go
现在运行命令,你就可以开始了