Comment initialiser un TrustManagerFactory avec de multiples sources de la confiance?

Ma demande a un fichier de clés contenant de confiance des certificats auto-signés pour une utilisation dans le réseau local - dire mykeystore.jks. Je veux être en mesure de se connecter à des sites publics(dire google.com) ainsi que ceux de mon réseau local à l'aide des certificats auto-signés qui ont été configurés localement.

Le problème ici est que, lorsque je me connecte à https://google.com, chemin de la construction échoue, parce que la définition de mon propre fichier de clés remplace la valeur par défaut du fichier de clés contenant des autorités de certification racine fourni avec le JRE, rapports à l'exception

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Cependant, si je importer un certificat CA dans mon propre fichier de clés (mykeystore.jks), il fonctionne très bien. Est-il un moyen de soutenir à la fois?

J'ai ma propre TrustManger à cette fin,

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 */
            }
        }
    }

J'ai ensuite initialiser le SSLContext,

TrustManager[] trustManagers =
            new TrustManager[] { new CustomX509TrustManager(keystore) };
SSLContext customSSLContext =
        SSLContext.getInstance("TLS");
customSSLContext.init(null, trustManagers, null);

et de définir la prise en usine,

HttpsURLConnection.setDefaultSSLSocketFactory(customSSLContext.getSocketFactory());

Le programme principal,

URL targetServer = new URL(url);
HttpsURLConnection conn = (HttpsURLConnection) targetServer.openConnection();

Si je n'ai pas mis mon propre gestionnaires des fonds, il se connecte à https://google.com l'amende juste. Comment puis-je obtenir un "défaut de confiance manager", qui désigne à la clé par défaut magasin?

OriginalL'auteur varrunr | 2014-04-17