如何使用多个信任源初始化TrustManagerFactory? [英] How do I initialize a TrustManagerFactory with multiple sources of trust?

查看:315
本文介绍了如何使用多个信任源初始化TrustManagerFactory?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序有一个个人密钥库,其中包含可在本地网络中使用的可信自签名证书 - 例如 mykeystore.jks 。我希望能够使用已在本地配置的自签名证书连接到公共站点(例如google.com)以及本地网络中的站点。

My application has a personal keystore containing trusted self-signed certificates for use in the local network - say mykeystore.jks. I wish to be able to connect to public sites(say google.com) as well as ones in my local network using self-signed certificates which have been provisioned locally.

这里的问题是,当我连接到 https:// google时.com ,路径构建失败,因为设置我自己的密钥库会覆盖包含与JRE捆绑在一起的根CA的默认密钥库,报告异常

The problem here is that, when I connect to https://google.com, path building fails, because setting my own keystore overrides the default keystore containing root CAs bundled with the JRE, reporting the exception

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 ),它可以正常工作。有没有办法支持两者?

However, if I import a CA certificate into my own keystore(mykeystore.jks) it works fine. Is there a way to support both?

我有自己的TrustManger用于此目的,

I have my own TrustManger for this purpose,

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,

I then initialize the 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 就好了。如何获得指向默认密钥库的默认信任管理器?

If I don't set my own trust managers, it connects to https://google.com just fine. How do I get a "default trust manager" which points to the default key store?

推荐答案

中trustMgrFactory.init(keystore); 您正在使用自己的个人密钥库配置defaultTrustManager,而不是系统默认密钥库。

In trustMgrFactory.init(keystore); you're configuring defaultTrustManager with your own personal keystore, not the system default keystore.

基于阅读sun.security.ssl.TrustManagerFactoryImpl的源代码,它看起来像 trustMgrFactory.init((KeyStore)null); 将完全符合您的需要(加载系统默认密钥库) ,基于快速测试,它似乎对我有用。

Based on reading the source code for sun.security.ssl.TrustManagerFactoryImpl, it looks like trustMgrFactory.init((KeyStore) null); would do exactly what you need (load the system default keystore), and based on quick testing, it seems to work for me.

这篇关于如何使用多个信任源初始化TrustManagerFactory?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆