【问题标题】:Intermittent SSL error: unable to find valid certification path to requested target间歇性 SSL 错误:无法找到请求目标的有效证书路径
【发布时间】:2020-04-23 15:45:03
【问题描述】:

我正在处理通过 SSL 调用 rest 服务的 HttpClient - 我使用 Eclipse 作为 IDE。
我使用浏览器下载了其余服务证书并将其导入到我的 Java 密钥库中 java\jdk1.8.0_144\jre\lib\security\cacerts
大多数时候 ecerything 工作正常,我能够得到回应,
但我有这个间歇性 SSL 错误:无法找到请求目标的有效证书路径

我有一些理论为什么会发生,但我不确定理论是否正确并且我有一些疑问
关于它。

  1. 这是一种可能的情况吗? :如果目标上的节点很少(在负载均衡器下)并且我只有一个节点的证书?
  2. Eclipse 无法读取密钥库的间歇性权限问题?
  3. 是否有可能目标正在使用多个 SSL 证书而我只有一个?
  4. eclipse 正在使用这个路径 java\jdk1.8.0_144\
    我将证书添加到 java\jdk1.8.0_144\jre\lib\security\cacerts
    我还需要在 \java\jdk1.8.0_144\lib\security 下添加它吗?

如果您有任何意见,我将很高兴收到任何意见。

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:141)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392)
    ... 51 more

【问题讨论】:

  • 服务使用的证书是自签名的,还是不受已知证书颁发机构(或它信任的证书颁发机构)信任?
  • 我不认为它是自签名的。证书上写着“颁发者:我的组织名称”

标签: java eclipse ssl


【解决方案1】:
  1. 这是一种可能的情况吗? :如果目标上的节点很少(在负载均衡器下)并且我只有一个节点的证书?

如果负载平衡器处于 TCP 或 IP 级别,可能。它当然可以允许不同的后端进行自己的 TLS 终止,虽然给定域名(或更一般的主机名)的所有后端应该使用相同的证书,但有人可能犯了错误. 如果负载均衡器处于 HTTP(应用程序)级别,它需要执行 TLS 终止以处理 HTTP 请求(包括 cookie 等),因此只有负载均衡器上的证书很重要。

这也可能在没有明确的负载平衡器的情况下发生。一些系统通过让 DNS 在不同时间将它们的名称解析为不同的地址来进行非正式的 IP 级别平衡——通常但不一定是通过固定列表“循环”。结果,即使您发送到相同的名称,您的连接实际上也会发送到不同的、不同的服务器。其他人——尤其是像现在的 Cloudflare 这样的 CDN——使用“anycast”,其中名称解析为一致的地址,但该地址实际上可以转到不同的物理服务器。

见下文。

  1. Eclipse 无法读取密钥库的间歇性权限问题?

我对此表示怀疑。首先,需要明确的是,当您在 eclipse 中运行 Java 程序时,eclipse 实际上会创建一个单独的 JVM 来运行指定的程序,可以选择进行调试,并且可以配置标准 I/O,但默认为 eclipse 控制台窗口。需要读取 truststore 的是 JVM,默认情况下是文件 cacerts。 (Java 使用 keystore files -- 和KeyStore 类 -- 来存储几种密钥信息,其中 certs 只是其中一种。cacerts 文件是 jks 格式,但只包含受信任的证书其他方——名义上的 CA,因此得名——因此在功能上是一个信任库。)

如果读取 cacerts 时出现问题,您会得到与此不同的异常。

  1. 是否有可能目标正在使用多个 SSL 证书而我只有一个?

这当然是可能的。首先,如果实际上有多个服务器在执行终止,如上面的#1,这很容易发生错误。如果实际上有一个服务器或设备正在终止:

  • 如果您在映射到同一物理服务器的 URL 中使用多个主机名(域名),则物理服务器很可能对不同的“逻辑”服务器使用不同的证书(例如 Apache 中的“VirtualHost” )

  • 如果您对不同的连接使用不同的 TLS 密钥交换 算法,服务器可能需要(拥有和)使用不同的证书。例如,如果某些连接使用 ECDHE_RSA 密钥交换,而某些连接使用 ECDHE_ECDSA,则服务器必须使用包含 RSA 密钥的证书作为第一个,而另一个则包含 ECC 密钥,并且它们必须不同。但是,除非您的代码指定了您通常不应该指定的 TLS 详细信息,或者您正在设置安全属性以仅对某些执行禁用某些算法,否则 Java (JSSE) 客户端将始终提供相同的密码套件(以及密钥交换)并且服务器始终会收到此信息相同的选项列表通常会始终做出相同的选择。 (仅供参考:对于 TLS1.3,keyexchange 不再由 ciphersuite 控制,但 1.3 仅在 j11 up 中实现,而不是 j8。)

  • 最后,协议允许服务器为相同的主机名和密钥交换拥有多个不同的证书,并且可以任意(甚至随机)在它们之间进行选择。但是没有合理的理由这样做,而且我从来没有见过这样的服务器。

  1. 我将证书添加到 java\jdk1.8.0_144\jre\lib\security\cacerts 我还需要在 \java\jdk1.8.0_144\lib\security 下添加它吗?

没有。 JRE/lib/security/caerts 是正确的地方。正如我在上面所说,您的代码实际上是在 JVM 中运行的,它只使用 JRE,而不是 JDK,在那些与 j8 中的情况不同的版本中。 (较新的“模块化”Java 版本不再定义固定的 JRE;想法是您可以创建定制的 JVM。)

间歇性多久?如果这种情况发生在每小时一次并且每小时只有几百个请求,我会打开 javax.net.debug=ssl,handshake,trustmanager 并重定向或捕获标准输出,并查看它以查看何时和使用什么证书是/实际使用的什么结果。 OTOH,如果每十亿个请求通过该日志文件发生一次,则要困难得多。

【讨论】:

    猜你喜欢
    • 2015-04-04
    • 1970-01-01
    • 2014-05-26
    • 2017-09-19
    • 2016-11-20
    • 1970-01-01
    • 2013-05-24
    • 1970-01-01
    • 2020-03-01
    相关资源
    最近更新 更多