如何忽略 PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException?
Posted
技术标签:
【中文标题】如何忽略 PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException?【英文标题】:How to ignore PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException? 【发布时间】:2012-11-17 14:18:49 【问题描述】:尝试向 http 服务器发布请求时出现以下异常:
这是我使用的代码
URL url = new URL(
"https://www.abc.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
// wr.writeBytes(params);
wr.flush();
wr.close();
BufferedReader br = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String line = null;
while ((line = br.readLine()) != null)
System.out.println(line);
这是一个例外:
Exception in thread "main" 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:1731)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:925)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1014)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
at com.amazon.mzang.tools.httpchecker.CategoryYank.getPV(CategoryYank.java:32)
at com.amazon.mzang.tools.httpchecker.CategoryYank.main(CategoryYank.java:18)
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:323)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
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:1185)
... 13 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:318)
... 19 more
服务器不归我所有。有没有办法忽略这个异常?
【问题讨论】:
不要忽略这个异常。在您的信任库中导入证书(经过一些手动验证)。忽略证书错误会使连接容易受到潜在的 MITM 攻击。 有时候,信任对客户端来说并不重要,但服务器仍然使用 https。 我有时会收到此错误 - 使用同一台服务器。一秒钟后再次尝试请求通过。服务器是 botcompany.de 并具有 LetsEncrypt 证书。这怎么解释? Comodo证书从来没有这个问题。不知道证书是否是原因。服务器正在运行 NanoHTTPD。 这能回答你的问题吗? Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error? 【参考方案1】:如果您想完全忽略证书,请在此处查看答案:Ignore self-signed ssl cert using Jersey Client
尽管这会使您的应用容易受到中间人攻击。
或者,尝试将证书作为受信任的证书添加到您的 java 商店。 这个网站可能会有所帮助。 http://blog.icodejava.com/tag/get-public-key-of-ssl-certificate-in-java/
这是另一个线程,展示了如何将证书添加到您的商店。 Java SSL connect, add server cert to keystore programmatically
关键是:
KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(someCert);
ks.setEntry("someAlias", newEntry, null);
【讨论】:
这个解决方案对我有用:***.com/a/59087392/4507034【参考方案2】:我已使用以下代码覆盖我的项目中的 SSL 检查,它对我有用。
package com.beingjavaguys.testftp;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
/**
* Fix for Exception in thread "main" 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
*/
public class ConnectToHttpsUrl
public static void main(String[] args) throws Exception
/* Start of Fix */
TrustManager[] trustAllCerts = new TrustManager[] new X509TrustManager()
public java.security.cert.X509Certificate[] getAcceptedIssuers() return null;
public void checkClientTrusted(X509Certificate[] certs, String authType)
public void checkServerTrusted(X509Certificate[] certs, String authType)
;
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier()
public boolean verify(String hostname, SSLSession session) return true;
;
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
/* End of the fix*/
URL url = new URL("https://nameofthesecuredurl.com");
URLConnection con = url.openConnection();
Reader reader = new InputStreamReader(con.getInputStream());
while (true)
int ch = reader.read();
if (ch == -1)
break;
System.out.print((char) ch);
【讨论】:
不遵守合同。 在您对sc.init()
的调用中,第三个参数可能是null
。 (将提供默认值。)
谢谢,此修复将忽略所有无效证书。当证书每 3 个月自动更新一次时,这非常有用,例如 Let's Encrypt 证书,并且您不能真正每 3 个月在 java 信任库中手动安装证书...
这仅适用于 HTTP,对吗?但不是 SMTP。我用 SMTP 对此进行了测试,没有做任何事情(仍然有相同的证书错误......直到我最终将证书添加到密钥库)。
感谢这对我有用...【参考方案3】:
为您的JSoup 命令将validateTLSCertificates
属性设置为false
。
Jsoup.connect("https://google.com/").validateTLSCertificates(false).get();
【讨论】:
【参考方案4】:FWIW,在 Ubuntu 10.04.2 LTS 上安装 ca-certificates-java 和 ca-certificates 包为我解决了这个问题。
【讨论】:
天啊,在与我的旧 Ubuntu 10.04 VM 战斗 6 小时后,这修复了那个讨厌的错误。这个版本太旧了,我不得不修改 sources.list 因为这些包返回 404 askubuntu.com/questions/805523/apt-get-update-for-ubuntu-10-04【参考方案5】:我在执行下面的 spring-boot + RestAssured 简单测试时遇到了同样的错误。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static com.jayway.restassured.RestAssured.when;
import static org.apache.http.HttpStatus.SC_OK;
@RunWith(SpringJUnit4ClassRunner.class)
public class GeneratorTest
@Test
public void generatorEndPoint()
when().get("https://bal-bla-bla-bla.com/generators")
.then().statusCode(SC_OK);
在我的情况下,简单的解决方法是添加“useRelaxedHTTPSValidations()”
RestAssured.useRelaxedHTTPSValidation();
那么测试看起来像
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static com.jayway.restassured.RestAssured.when;
import static org.apache.http.HttpStatus.SC_OK;
@RunWith(SpringJUnit4ClassRunner.class)
public class GeneratorTest
@Before
public void setUp()
RestAssured.useRelaxedHTTPSValidation();
@Test
public void generatorEndPoint()
when().get("https://bal-bla-bla-bla.com/generators")
.then().statusCode(SC_OK);
【讨论】:
【参考方案6】:如果问题是缺少中间证书,您可以启用 Oracle JRE 自动下载缺少的中间证书,如 this answer 中所述。
只需设置Java系统属性-Dcom.sun.security.enableAIAcaIssuers=true
为此,服务器的证书必须提供中间证书(证书的颁发者)的 URI。据我所知,这也是浏览器所做的并且应该同样安全——不过我不是安全专家。
编辑:如果我没记错的话,这似乎至少适用于 Java 8 并且是 documented here for Java 9。
【讨论】:
您应该提及您的解决方案适用于哪个 Java 版本。试过了,它不适用于 JDK 1.7.0_13【参考方案7】:如果您使用的是 CloudFoundry,那么您必须将 jar 连同具有证书的密钥库一起显式推送。
【讨论】:
【参考方案8】:我也遇到了同样的问题。我试图以clean install
目标构建项目。我只是在运行配置中将其更改为clean package -o
。然后我重新构建了这个项目,它对我有用。
【讨论】:
【参考方案9】:我也遇到过这个问题。我有 JDK 1.8.0_121
。我将 JDK 升级到 1.8.0_181
,它就像一个魅力。
【讨论】:
【参考方案10】:我在 Apache Tomcat/7.0.67 和 Java JVM 版本:1.8.0_66-b18 上也有同样的问题。刚刚升级到 JRE 1.8.0_241 似乎问题已经解决了。
【讨论】:
以上是关于如何忽略 PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException?的主要内容,如果未能解决你的问题,请参考以下文章
sun.security.validator.ValidatorException 的 JDBC 异常:PKIX 路径构建失败
PKIX 路径构建失败:我将证书添加到 carcert 仍然失败