【问题标题】:Downloading website over HTTPS fails通过 HTTPS 下载网站失败
【发布时间】:2015-05-27 17:58:59
【问题描述】:

这是不起作用的示例:

public class Temp {
  public static void main(String[] args) throws Exception {
    new URL("https://float.software").openConnection().getInputStream();
  }
}

在我的浏览器中转到https://float.software/ 工作正常。但是java抛出了这个异常:

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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1478)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:957)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:892)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1512)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1440)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at fb.Temp.main(Temp.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(PKIXValidator.java:387)
    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:324)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460)
    ... 13 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
    ... 19 more

当我查看其他答案时,他们都在谈论安装证书。我认为我不必安装证书。这不是自签名的。它使用真正的证书颁发机构。 Python 可以很好地下载这个 URL。铬也是如此。 Java 没有。

编辑:对于那些说 Comodo 是尚未添加到 java 中的较新权限的人,它是作为 Java 5 中的根添加的。请参阅http://forums.comodo.com/comodo-cleaning-essentials-killswitch-autoruns-cce/how-do-i-unblock-a-processexecutable-t17086.0.html

【问题讨论】:

    标签: java ssl https certificate


    【解决方案1】:

    如果您查看此域的 SSLLabs report,您将看到两种可能的认证路径:

    • 第一个(较短的)一端期望客户端信任“COMODO RSA 证书颁发机构”。尽管这个 CA 自 2010 年起就有效,但它只是在最近(大约半年)前才包含在 Firefox 等浏览器中,请参阅 https://bugzilla.mozilla.org/show_bug.cgi?id=1062589。在大多数浏览器之外,您不会发现此 CA 是受信任的,即在 Java 或类似的信任存储中(Java 不使用系统信任存储)。
    • 另一个较长的证书路径需要一个受信任的根 CA“AddTrust External CA Root”。这个 CA 多年来一直包含在浏览器和操作系统中,并且可能也在 Java 信任库中。不幸的是,要验证此证书路径,需要服务器未提供的附加链证书(在 SSLLabs 报告中标记为“额外下载”)。

    由于 Java 不包含来自第一个路径的 Root-CA,因此无法对其进行验证。由于缺少链证书,它无法验证第二条路径。这意味着验证失败。

    Python 可以很好地下载这个 URL。铬也是如此。

    Chrome 具有更新的根 CA。 Chrome 也会尝试下载丢失的链证书,而 Java、Python 等则不会。

    Python 最近才开始默认验证证书,即从 2.7.9+ 和 3.4.3+ 开始。所有以前的(这意味着大多数安装的)版本都没有验证证书(使用请求库时除外),所以它只是工作(典型问题:没有人注意到这是不安全的,因为它似乎工作)。见https://www.python.org/dev/peps/pep-0476/

    【讨论】:

    • 好像有两种解决方案:1.给java添加comodo权限证书2.有java自动下载证书——你觉得哪个更容易?
    • 第一个只是添加一个新的受信任的 CA,这并不难。另一个是更改 Java 的证书验证部分,这可能不是您想要做的,我相信这并不容易。
    • 是否有一种简单的方法可以在运行时添加受信任的 CA?我不想在部署到的每台 linux 服务器上都安装证书。
    • 在这方面我对 Java 并不熟悉,但根据 stackoverflow.com/questions/1650596/… 的说法,它看起来并不简单。但我可以说,使用 Perl 可以在一行内完成 :)
    • 您可以联系网站所有者,看看他们是否愿意将中间证书(带有指纹的证书:f5ad0bcc1ad56cd150725b1c866c30ad92ef21b0)添加到链中
    【解决方案2】:

    如果您使用的是旧版本的 Java,您可能需要更新您的 cacerts 文件。 float.software 的 SSL 证书由“COMODO RSA 证书颁发机构”签署,该证书自 2014 年 2 月起才有效。您的 Java 安装可能比这更旧。

    另外,请注意 Python。并非所有 HTTPS 实现都会验证远程证书。

    【讨论】:

    • 你是对的。我刚刚检查了 JDK 8,它不包含“COMODO RSA 证书颁发机构”。您必须将其添加到 cacerts
    • 有没有办法在运行时将其添加到 cacerts 中?我不想在部署到的每台 linux 服务器上都安装证书。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 2019-05-10
    • 2014-02-14
    相关资源
    最近更新 更多