java - 我可以在不重新启动 JVM 的情况下将新证书添加到 keystore 吗?

标签 java certificate x509certificate keystore keytool

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

或者,是否可以为特定 URL 连接指定一个不在 keystore 中的证书?

最佳答案

事实证明,您可以指定特定的证书以用于特定的 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);
  }
}

关于java - 我可以在不重新启动 JVM 的情况下将新证书添加到 keystore 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3964703/

相关文章:

java - 使用 enterpriseApplication 简单刷新 LIberty Websphere Sphere 应用程序服务器 16

java - 我可以以某种方式覆盖消息传递中的 JMS 提供程序行为吗?

powershell - wap cmdlet - 添加证书错误

apache - 使用智能卡的 SSL 客户端身份验证

c# - SVN 凭据

c# - C# 中的 X509 指南/教程

.net - 为什么在创建 X509Certificate2 对象时会收到拒绝访问错误?

java - Codename One 中带有 lambda 的 Android native 代码无法正常工作

java - 透明 UI (+UIManager) 工件

.net - 安全网络套接字 (WSS) 证书签名