实现X509TrustManager – 将部分validation传递给现有validation程序

我需要忽略PKIX路径构建exception

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderExc ption: unable to find valid certification path to requested target 

我知道如何通过编写我自己的实现X509TrustManager的类来实现这一点,我总是从isServerTrusted return true

但是,我不想信任所有服务器和所有客户端。

  • 我希望像当前​​一样为客户端完成所有默认validation。
  • 对于服务器,我想忽略仅针对一个特定证书的服务器证书validation,但是希望继续进行validation,就像当前所做的那样(例如,使用cacerts商店)。

我怎样才能实现这样的目标 – 即在我更换之前将部分validation传递给X509TrustFactory对象。

这就是我想要做的

 public boolean isServerTrusted(X509Certificate[] chain) { if(chain[0].getIssuerDN().getName().equals("MyTrustedServer") && chain[0].getSubjectDN().getName().equals("MyTrustedServer")) return true; // else I want to do whatever verification is normally done } 

另外我不想打扰现有的isClientTrustedvalidation。

我怎样才能做到这一点?

您可以使用以下内容来获取现有的默认信任管理器并将其包装在您自己的管理器中:

 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 x509Tm = null; for (TrustManager tm : tmf.getTrustManagers()) { if (tm instanceof X509TrustManager) { x509Tm = (X509TrustManager) tm; break; } } // Wrap it in your own class. final X509TrustManager finalTm = x509Tm; X509TrustManager customTm = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return finalTm.getAcceptedIssuers(); } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { finalTm.checkServerTrusted(chain, authType); } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { finalTm.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); 

然后,您可以在finalTm.checkServerTrusted(chain, authType);周围实现自己的逻辑finalTm.checkServerTrusted(chain, authType);

但是,您应确保对要忽略的特定证书进行例外处理。

您在下面所做的是通过任何具有这些Issuer DN和Subject DN(不难伪造)的证书:

 if(chain[0].getIssuerDN().getName().equals("MyTrustedServer") && chain[0].getSubjectDN().getName().equals("MyTrustedServer")) return true; 

您可以从已知引用加载X509Certificate实例,并比较链中的实际值。

此外, checkClientTrustedcheckServerTrusted不是返回truefalse方法,而是默认情况下将以静默方式成功的void方法。 如果您期望的CertificateException显式抛出CertificateException