5

我想在不重新启动正在运行的服务的情况下将新证书导入密钥库。那可能吗?

或者,是否可以为特定 URL 连接指定不在密钥库中使用的证书?

4

1 回答 1

7

事实证明,您可以指定用于特定 URL 获取的特定证书;本质上,您需要创建自己的 TrustManager 并将其换入,如下所示:

public String fetchFromUrl(String urlString) throws IOException {
  URL url = new URL(urlString);
  URLConnection conn = url.openConnection();

  if (conn instanceof HttpsURLConnection && shouldSubstituteCert(url)) {
    HttpsURLConnection sslConn = (HttpsURLConnection) conn;
    try {
      SSLContext context = SSLContext.getInstance("SSL");
      context.init(null, new TrustManager[] {new MyTrustManager()}, null);
      sslConn.setSSLSocketFactory(context.getSocketFactory());
    } catch (Exception e) {
      e.printStackTrace();
      throw new IOException("Error creating custom keystore", e);
    }
  }

  return readAll(conn.getInputStream());
}

private static class MyTrustManager implements X509TrustManager {
  private final X509TrustManager trustManager;
  public MyTrustManager() throws 
      KeyStoreException, NoSuchAlgorithmException, 
      CertificateException, IOException {

    // Load a KeyStore with only our certificate
    KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
    store.load(null, null);
    Certificate cert = loadPemCert();
    store.setCertificateEntry("me.com", cert);

    // create a TrustManager using our KeyStore
    TrustManagerFactory factory = TrustManagerFactory.getInstance(
        TrustManagerFactory.getDefaultAlgorithm());
    factory.init(store);
    this.trustManager = getX509TrustManager(factory.getTrustManagers());
  }

  public void checkClientTrusted(X509Certificate[] chain, String authType)
      throws CertificateException {
    trustManager.checkClientTrusted(chain, authType);
  }

  public void checkServerTrusted(X509Certificate[] chain, String authType)
      throws CertificateException {
    trustManager.checkServerTrusted(chain, authType);
  }

  public X509Certificate[] getAcceptedIssuers() {
    return trustManager.getAcceptedIssuers();
  }

  private static X509TrustManager getX509TrustManager(TrustManager[] managers) {
    for (TrustManager tm : managers) {
      if (tm instanceof X509TrustManager) {
        return (X509TrustManager) tm;
      }
    }
    return null;
  }

  private Certificate loadPemCert() 
      throws CertificateException, IOException {
    InputStream stream = 
      this.getClass().getClassLoader().getResourceAsStream("cert.pem");

    CertificateFactory factory = CertificateFactory.getInstance("X.509");
    return factory.generateCertificate(stream);
  }
}
于 2010-10-19T21:05:27.627 回答