Java 应用程序中的 PKIX 路径构建失败
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18378869/
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 in Java application
提问by JavaCake
I have been struggling for almost one week to get my applications up running after moving my applications from Windows 2000 to Windows 2008 R2 Server.
在将我的应用程序从 Windows 2000 移动到 Windows 2008 R2 Server 之后,我一直在努力让我的应用程序运行近一个星期。
The procedure:
步骤:
- Installed Java JDK 1.7.0_25
- Set system environment variable
JAVA_HOME
toC:\Progra~1\Java\jdk1.7.0_25\
- Imported the certificate into cacerts with
keytool
- Ensured that the certificate exists in
keytool
with-list
.
- 已安装 Java JDK 1.7.0_25
- 将系统环境变量设置
JAVA_HOME
为C:\Progra~1\Java\jdk1.7.0_25\
- 将证书导入到 cacerts 中
keytool
- 确保在存在该证书
keytool
用-list
。
I have tried to repeat step 3with InstallCert
to ensure that i havent messed anything up.
我曾试图重复步骤3用InstallCert
,以确保我还没有把事情搞得一团糟。
The above methods did not solve my problem, so i tried to do it programmatically:
上述方法没有解决我的问题,所以我尝试以编程方式进行:
System.setProperty("javax.net.ssl.trustStore",
"C:/Progra~1/Java/jdk1.7.0_25/jre/lib/security/cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Still without any luck. I am stuck and not quite sure which direction to go from here.
仍然没有任何运气。我被卡住了,不太确定从这里往哪个方向。
Stack trace:
堆栈跟踪:
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(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1886)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1341)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:515)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:153)
at util.SMS.send(SMS.java:93)
at domain.ActivationSMSSenderMain.sendActivationMessagesToCustomers(ActivationSMSSenderMain.java:80)
at domain.ActivationSMSSenderMain.<init>(ActivationSMSSenderMain.java:44)
at domain.ActivationSMSSenderMain.main(ActivationSMSSenderMain.java:341)
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:385)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1323)
... 14 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:196)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
... 20 more
UPDATE:
更新:
Both
System.out.println(System.getProperty("javax.net.ssl.trustStore"));
and
System.out.println(System.getProperty("javax.net.ssl.keyStore"));
双方
System.out.println(System.getProperty("javax.net.ssl.trustStore"));
并
System.out.println(System.getProperty("javax.net.ssl.keyStore"));
returns null
.
返回null
。
采纳答案by jb1
I ran into similar issues whose cause and solution turned out both to be rather simple:
我遇到了类似的问题,其原因和解决方案都非常简单:
Main Cause: Did not import the proper cert using keytool
主要原因:没有使用 keytool 导入正确的证书
NOTE: Only import root CA (or your own self-signed) certificates
注意:仅导入根 CA(或您自己的自签名)证书
NOTE: don't import an intermediate, non certificate chain root cert
注意:不要导入中间的、非证书链根证书
Solution Example for imap.gmail.com
imap.gmail.com 的解决方案示例
Determine the root CA cert:
openssl s_client -showcerts -connect imap.gmail.com:993
in this case we find the root CA is Equifax Secure Certificate Authority
- Download root CA cert.
- Verify downloaded cert has proper SHA-1 and/or MD5 fingerprints by comparing with info found here
Import cert for
javax.net.ssl.trustStore
:keytool -import -alias gmail_imap -file Equifax_Secure_Certificate_Authority.pem
- Run your java code
回答by Sean Baker
Per your pastebin, you need to add the proxy.tkk.com
certificate to the truststore.
根据您的 pastebin,您需要将proxy.tkk.com
证书添加到信任库。
回答by user207421
You've imported the certificate into the truststore of the JRE provided in the JDK, but you are running the java.exe of the JRE installed directly.
您已将证书导入到 JDK 中提供的 JRE 的信任库中,但您正在运行直接安装的 JRE 的 java.exe。
EDIT
编辑
For clarity, and to resolve the morass of misunderstanding in the commentary below, you need to import the certificate into the cacerts
file of the JRE you are intending to use,and that will rarely if ever be the one shipping inside the JDK, because clients won't normally have a JDK. Anything in the commentary below that suggests otherwise should be ignored as not expressing my intention here.
为了清楚起见,并解决下面评论中的误解,您需要将证书导入到您打算使用的 JREcacerts
文件中,并且很少会在 JDK 内部传送证书,因为客户赢了通常没有 JDK。以下评论中任何暗示其他内容的内容都应该被忽略,因为这里没有表达我的意图。
A far better solution would be to create your owntruststore, starting with a copy of the cacerts
file, and specifically tell Java to use that one via the system property javax.net.ssl.trustStore.
更好的解决方案是创建您自己的信任库,从cacerts
文件的副本开始,并特别告诉 Java 通过系统属性使用该信任库javax.net.ssl.trustStore.
You should make building this part of your build process, so as to keep up to date with changes I the cacerts
file caused by JDK upgrades.
您应该将构建这部分作为构建过程的一部分,以便及时了解cacerts
由 JDK 升级引起的文件更改。
回答by Mohammed Irfan Tirupattur
If you are using Eclipse just cross check in Eclipse Windows--> preferences---->java---> installed JREsis pointing the current JRE and the JRE where you have configured your certificate. If not remove the JRE and add the jre where your certificate is installed
如果您使用的是 Eclipse,只需在 Eclipse Windows--> 首选项--> java ---> 安装的 JRE 中交叉检查当前 JRE 和您配置证书的 JRE。如果没有删除 JRE 并在安装证书的位置添加 jre
回答by acohen
In my case the issue was resolved by installing Oracle's official JDK 10as opposed to using the default OpenJDK that came with my Ubuntu. This is the guide I followed: https://www.linuxuprising.com/2018/04/install-oracle-java-10-in-ubuntu-or.html
在我的情况下,问题是通过安装Oracle 的官方 JDK 10而不是使用我的 Ubuntu 附带的默认 OpenJDK 解决的。这是我遵循的指南:https: //www.linuxuprising.com/2018/04/install-oracle-java-10-in-ubuntu-or.html
回答by Ilya Lysenko
On Windowsyou can try these steps:
在 Windows 上,您可以尝试以下步骤:
- Download a root CA certificate from the website.
- Find a file jssecacerts in the directory
/lib/security
with JRE (you can use a comandSystem.out.println(System.getProperty("java.home");
to find the folder with the current JRE). Make a backup of the file. - Download a program portecle.
- Open the jssecacerts file in portecle.
- Enter the password: changeit.
- Import the downloaded certificate with porticle (Tools > Import Trusted Certificate).
- Click Save.
- Replace the original file jssecacerts.
- 从网站下载根 CA 证书。
- 在
/lib/security
JRE所在的目录中找到一个文件jssecacerts (可以使用命令System.out.println(System.getProperty("java.home");
查找当前JRE所在的文件夹)。备份文件。 - 下载程序portecle。
- 在 portecle 中打开 jssecacerts 文件。
- 输入密码:changeit。
- 使用 porticle 导入下载的证书(工具 > 导入可信证书)。
- 单击保存。
- 替换原来的文件jssecacerts。