你可以使用一个类似的模式,我在之前的回答中提到(针对不同的问题)。
从本质上讲,掌握默认的信任pipe理器,创build第二个使用自己的信任存储的信任pipe理器。 将它们都包装在委托调用两者的自定义信任pipe理器实现中(当一个失败的时候再次落在另一个实例上)。
TrustManagerFactory tmf = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); // Using null here initialises the TMF with the default trust store. tmf.init((KeyStore) null); // Get hold of the default trust manager X509TrustManager defaultTm = null; for (TrustManager tm : tmf.getTrustManagers()) { if (tm instanceof X509TrustManager) { defaultTm = (X509TrustManager) tm; break; } } FileInputStream myKeys = new FileInputStream("truststore.jks"); // Do the same with your trust store this time // Adapt how you load the keystore to your needs KeyStore myTrustStore = KeyStore.getInstance(KeyStore.getDefaultType()); myTrustStore.load(myKeys, "password".toCharArray()); myKeys.close(); tmf = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(myTrustStore); // Get hold of the default trust manager X509TrustManager myTm = null; for (TrustManager tm : tmf.getTrustManagers()) { if (tm instanceof X509TrustManager) { myTm = (X509TrustManager) tm; break; } } // Wrap it in your own class. final X509TrustManager finalDefaultTm = defaultTm; final X509TrustManager finalMyTm = myTm; X509TrustManager customTm = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { // If you're planning to use client-cert auth, // merge results from "defaultTm" and "myTm". return finalDefaultTm.getAcceptedIssuers(); } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { try { finalMyTm.checkServerTrusted(chain, authType); } catch (CertificateException e) { // This will throw another CertificateException if this fails too. finalDefaultTm.checkServerTrusted(chain, authType); } } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { // If you're planning to use client-cert auth, // do the same as checking the server. finalDefaultTm.checkClientTrusted(chain, authType); } }; SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[] { customTm }, null); // You don't have to set this as the default context, // it depends on the library you're using. SSLContext.setDefault(sslContext);
您不必将该上下文设置为默认上下文。 你如何使用它取决于你正在使用的客户端库(以及从哪里得到它的套接字工厂)。
这就是说,原则上,你总是必须根据需要更新信任库。 “Java 7 JSSE参考指南”对此有一个“重要提示”,现在在同一指南的第8版中降级为“注释” :
JDK在java-home / lib / security / cacerts文件中附带有限数量的可信根证书。 如keytool参考页所述,如果您将此文件用作信任库,则您有责任维护(即添加和删除)此文件中包含的证书。
根据您联系的服务器的证书configuration,您可能需要添加其他根证书。 从相应的供应商获取所需的特定根证书。