1

我尝试通过 java 内置功能为此 ( HttpURLConnection) 建立 https 连接。但我得到了这个例外:

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)
...
...

我的证书链是:

Root certificate -> Intermediate certificate -> Web server certificate

根据“路径发现”的含义,使用的证书是正确的。信任锚是根证书,它是在我系统上的 java 密钥库中导入的。中间证书不是……但是

  1. 中间证书由我信任的根签名 - 所以我也信任中间证书。
  2. Web 服务器证书使用我信任的中间证书签名(第 1 点)

那么验证必须成功通过吗?我有什么问题吗?

我在某处读到这个:

浏览器可以进行自动发现,服务器到服务器不能。

但是缺少此功能是非常基本的。是否有明确的方法来进行这种自动发现

* *更新

是的,这就是问题所在,GPI。我很困惑,因为浏览器可以验证服务器证书,但 java 应用程序不能。这种行为的原因是:

  • 服务器只发送最终证书,而不是整个证书链;
  • 证书是最近买的,用比较新的中间证书签名;
  • 浏览器具有相对最新的证书列表,包括中间证书;
  • java有相对的不是最新的证书列表,中间证书不在里面。
  • 浏览器通过中间证书验证最终证书 java 无法检查证书链,因为: 1. 链未发送;2. 最终证书(中间证书)的签名者不是信任锚。

解决方案可能是:

  • 服务器返回整个证书链
  • 要在 java 信任库中添加的中间证书
4

2 回答 2

3

我相信您已经检查了您的链,因此我们可以理所当然地认为RootCert签署了IntermediateCertIntermediateCert签署了ServerCert,具有有效的 X500 名称链和所有......

也就是说,您的逻辑是有效的,相信RootCert就足够了,但不要忘记,为了构建路径,您的客户端必须拥有路径中的所有证书。

在您的情况下,如果您仅信任根证书,则由服务器来宣传证书链的其余部分(中间和最终)。如果没有人“给”HTTP客户端中间证书,那么客户端将失败,因为从服务器不知道中间是不可能的。

-Djavax.net.debug=all通过使用该选项启动客户端,您实际上可以看到您的服务器证书链是什么。如果链的长度为 1,那么您的服务器只公布最终证书,客户端无法猜测中间证书存在。

(也可以使用浏览器检查并要求查看服务器证书,但您应该注意,浏览器会向您显示到信任锚的整个路径,因此如果您想推断服务器链是什么,您必须从此路径中删除浏览器的锚点)。

在生产服务上,您应该参考您的证书提供商的网站,以了解什么被视为根证书(它可能不是最高级别的证书)。这个有效的根应该是您的客户端的信任锚,并且任何服务器都应该从路径中的最后一个证书(通用名称是服务器的 DNS 名称的那个)至少通告链中的所有其他证书。

于 2013-04-12T15:56:00.807 回答
0

In order to connect via Https you need to use an HttpsURLConnection object. You cannot create a connection with an HttpURLConnection object.

于 2013-04-12T15:12:46.727 回答