我尝试通过 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 密钥库中导入的。中间证书不是……但是
- 中间证书由我信任的根签名 - 所以我也信任中间证书。
- Web 服务器证书使用我信任的中间证书签名(第 1 点)
那么验证必须成功通过吗?我有什么问题吗?
我在某处读到这个:
浏览器可以进行自动发现,服务器到服务器不能。
但是缺少此功能是非常基本的。是否有明确的方法来进行这种自动发现?
* *更新
是的,这就是问题所在,GPI。我很困惑,因为浏览器可以验证服务器证书,但 java 应用程序不能。这种行为的原因是:
- 服务器只发送最终证书,而不是整个证书链;
- 证书是最近买的,用比较新的中间证书签名;
- 浏览器具有相对最新的证书列表,包括中间证书;
- java有相对的不是最新的证书列表,中间证书不在里面。
- 浏览器通过中间证书验证最终证书 java 无法检查证书链,因为: 1. 链未发送;2. 最终证书(中间证书)的签名者不是信任锚。
解决方案可能是:
- 服务器返回整个证书链
- 要在 java 信任库中添加的中间证书