我尝试通过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密钥库中导入。中间证书不是......但是
所以验证必须成功通过?我搞错了吗?
在某处,我读到了这个:
浏览器可以进行自动发现,服务器到服务器则不行。
但缺少此功能是非常基本的。有没有明确的方法auto-discovery?
* * 更新
是的,这是问题,GPI。我很困惑,因为浏览器可以验证服务器证书但java应用程序不能。 这种行为的原因是:
解决方案可能是:
答案 0 :(得分:3)
我相信您已经检查了您的链,因此我们可以理所当然地认为 RootCert 已签名 IntermediateCert 和 IntermediateCert 已签名 ServerCert ,具有有效的X500名称链接和所有...
那就是说,你的逻辑是有效的,信任 RootCert 就足够了,但是不要忘记为了建立一个路径,你的客户必须拥有全部路径中的证书。
在您的情况下,如果您仅信任根证书,则由服务器来通告证书链的其余部分(中间和最终)。如果没有人“给”HTTP客户端中间证书,那么客户端将失败,因为从 Root 到 Server 而不知道 Intermediate 不是可能的。
通过使用-Djavax.net.debug=all
选项启动客户端,您实际上可以看到服务器证书链是什么。如果链的长度为1,那么您的服务器只会通告最终证书,客户端无法猜测中间证书是否存在。
(也可以使用浏览器检查并要求查看服务器证书,但是您应该注意浏览器将显示信任锚的整个路径,因此如果您想要推断服务器链是什么,你必须从这条路径中移除浏览器的锚点。)
在生产服务上,您应该参考您的证书提供商的网站,以了解什么是根证书(它可能不是最高级别的证书)。这个有效的root应该是你的客户端的信任锚,并且任何服务器都应该至少通告链中的最后一个证书(路径中的最后一个证书,其公用名是服务器的DNS名称)。
答案 1 :(得分:0)
要通过Https连接,您需要使用HttpsURLConnection对象。您无法使用HttpURLConnection对象创建连接。