【问题标题】:Error when connecting to URL - PKIX path building failed连接到 URL 时出错 - PKIX 路径构建失败
【发布时间】:2015-10-22 15:18:08
【问题描述】:

我正在尝试连接到网页以收集信息,并且我正在使用 jsoup 来解析 HTML。但是,每当我尝试连接到 URL 以下载源代码时,都会收到一条错误消息,说明有关 PKIX 构建路径的信息。 我环顾四周,发现的所有内容都说要将网站的 CA 根证书添加到我的信任库中,我这样做了,但问题仍然存在(CA 根证书已经存在)。我可以通过网络浏览器连接到网站,但不能通过 URL 类。这是我可以编写的最基本的代码,它会产生错误。

public class URLConnectStart {
    public static void main(String[] args) {
        try {
            URL u = new URL("https://ntst.umd.edu/soc/");
            u.openStream();     
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这是错误

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.getInputStream0(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
    at java.net.URL.openStream(Unknown Source)
    at URLConnectStart.run(URLConnectStart.java:14)
    at URLConnectStart.main(URLConnectStart.java:8)
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)
    ... 16 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 22 more

来自 chrome 的有关网站证书的信息

任何帮助将不胜感激。这不是一个关键的应用程序,所以安全性并不是那么重要,但如果我能保持安全性,我宁愿这样做。无论如何,我想做的就是通过代码下载这个网站的 HTML。

谢谢。

【问题讨论】:

    标签: java ssl encryption certificate pkix


    【解决方案1】:

    完成证书链所需的网站does not provide an intermediate certificate。一些用户代理/浏览器具有称为 AIA 追逐的功能,它们可以在其中下载必要的中间体,但 Java 客户端不是其中之一。

    如果您是站点管理员,解决此问题的正确方法是提供中间证书,以便发送完整的链。即使您是最终用户,也请考虑联系网站以解决此问题。由于此问题,使用 Android 浏览器的人也将无法访问此站点,除非接受安全警告。

    同时,如果您想在您的客户中解决此问题,您可以download the missing intermediate certadd it to your Java certificate store

    【讨论】:

    • 这条评论对理解问题很有帮助,但由于某种原因,我无法解决问题。我能够将证书添加到密钥库,但是当我运行程序时,我仍然得到同样的错误。密钥库中应该有超过 1 个条目,还是我需要在我的代码中添加一些内容?
    • 证书存储通常应包含与 JDK/JRE 捆绑在一起的所有根 CA 证书,以及您可能添加的任何其他证书。我的默认 cacert 文件(Java 1.8.0_66)有 93 个证书,在将中间文件添加到此存储后,我能够使用您的代码 sn-p 连接到 URL。
    • 好的,我发现我做错了什么。我在 bin 文件夹中创建了一个新的 cacerts,而不是使用 /lib/security 中的那个。我能够连接到该网站,我将就他们的证书问题联系管理员。感谢您的帮助。
    • 您似乎可以使用 JVM 参数 -Dcom.sun.security.enableAIAcaIssuers=true 激活中间证书 (AIA) 的自动下载。更多详情请见here
    【解决方案2】:

    您可以手动将证书安装到 java keystore。

    • 打开 chrome 并提供 URL。在地址栏中
    • 点击带有锁定图标的安全
    • 将出现带有一些选项的弹出窗口。
    • 选择 Certificate -> valid 链接就在其下方。
    • 点击详细信息选项卡并选择复制到文件
    • 给一些名字并保存它。

    清除任何别名是否存在的第一个命令(我更喜欢在 Windows 中从 JAVA_HOME 运行它,因此路径是相对于此的。如果您是从外部运行,请相应地更改路径。

    • keytool -delete -alias "c11" -keystore ../jre/lib/security/cacerts -storepass changeit -noprompt

    现在我们需要安装证书

    • keytool -import -file "C:\Certificateert\c1.cer" -keystore ../jre/lib/security/cacerts -alias "c11" -storepass changeit -noprompt

    密钥库的默认密码是 changeit

    如果您有多个证书,请将此命令添加到文本文件中,并将其保存为 bat 扩展名并放入 JAVA_HOME\bin 或任何您喜欢的位置.确保提到的路径是相对的。

    如果您的 jre 在 jdk 之外,请提供该路径。

    • keytool -import -file "C:\Certificate\c6.cer" -keystore "C:\Program Files\Java\jre1.8.0_181\lib\security\cacerts" -alias "c66 " -storepass changeit -noprompt

    【讨论】:

      猜你喜欢
      • 2011-01-18
      • 2019-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-05
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      相关资源
      最近更新 更多