我的应用程序有一个个人密钥库,其中包含可在本地网络中使用的可信自签名证书 – 例如mykeystore.jks.我希望能够使用已在本地配置的自签名证书连接到公共站点(例如google.com)以及本地网络中的站点.
这里的问题是,当我连接到https://google.com时,路径构建失败,因为设置我自己的密钥库会覆盖包含与JRE捆绑的根CA的默认密钥库,报告异常
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
但是,如果我将CA证书导入我自己的密钥库(mykeystore.jks),它可以正常工作.有没有办法支持两者?
我有自己的TrustManger用于此目的,
public class CustomX509TrustManager implements X509TrustManager {
X509TrustManager defaultTrustManager;
public MyX509TrustManager(KeyStore keystore) {
TrustManagerFactory trustMgrFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustMgrFactory.init(keystore);
TrustManager trustManagers[] = trustMgrFactory.getTrustManagers();
for (int i = 0; i < trustManagers.length; i++) {
if (trustManagers[i] instanceof X509TrustManager) {
defaultTrustManager = (X509TrustManager) trustManagers[i];
return;
}
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
try {
defaultTrustManager.checkServerTrusted(chain, authType);
} catch (CertificateException ce) {
/* Handle untrusted certificates */
}
}
}
然后我初始化SSLContext,
TrustManager[] trustManagers =
new TrustManager[] { new CustomX509TrustManager(keystore) };
SSLContext customSSLContext =
SSLContext.getInstance("TLS");
customSSLContext.init(null, trustManagers, null);
并设置套接字工厂,
HttpsURLConnection.setDefaultSSLSocketFactory(customSSLContext.getSocketFactory());
主程序,
URL targetServer = new URL(url);
HttpsURLConnection conn = (HttpsURLConnection) targetServer.openConnection();
如果我没有设置自己的信任管理器,它就连接到https://google.com就好了.如何获得指向默认密钥库的“默认信任管理器”?
本文探讨了在Java应用程序中如何同时使用自定义密钥库和默认JRE根CA证书来建立安全连接。问题在于,自定义TrustManager覆盖了默认的信任源,导致连接到如google.com等公共站点时出现证书验证失败。为解决这个问题,提出了实现自定义X509TrustManager,该管理器能够检查服务器证书,包括默认信任管理器和自定义密钥库中的证书。通过这种方式,可以在保持对本地自签名证书信任的同时,也能正确验证公共站点的证书。
1162

被折叠的 条评论
为什么被折叠?



