【问题标题】:How do I use client certificates in a client java application?如何在客户端 Java 应用程序中使用客户端证书?
【发布时间】:2019-05-11 14:03:29
【问题描述】:

这是一个我花了很长时间才弄清楚的话题。有零散的信息,一个人必须把所有东西放在一起。我希望通过这篇文章,我可以帮助其他人快速组装一个可行的解决方案。


我有一个 client-cert.pemclient-key.pem 和一个 root.pem 文件,我需要在我的 Java 客户端中使用它们来访问远程 REST API。

如何将它们打包到信任库中并使用它们进行 API 调用?

【问题讨论】:

    标签: java https certificate keystore


    【解决方案1】:

    为了将您的证书加载到您的应用程序中,您需要将它们打包到信任库中。

    创建信任库

    鉴于 3 个文件:

    • client-cert.pem
    • client-key.pem
    • root.pem

    在终端中运行以下命令。将PASSWORD 替换为您想要的密码。

    1. 将您的客户端密钥和证书打包到密钥库中。这将创建一个 PKCS12 密钥库文件。

      openssl pkcs12 -export \
          -inkey client-key.pem -in client-cert.pem \
          -out client.pfx -passout pass:PASSWORD \
          -name qlikClient
      
    2. 将密钥库添加到您的信任库。如果目的地不退出,它将创建一个信任库。这将创建一个PKCS12 信任库文件。默认情况下,它会创建一个专有格式的JKS 文件。通过指定-deststoretype PKCS12,您将创建一个行业标准格式的文件。

      keytool -importkeystore \
          -destkeystore truststore.pfx -deststoretype PKCS12 -deststorepass PASSWORD \
          -srckeystore client.pfx -srcstorepass PASSWORD -srcstoretype PKCS12 \
          -alias qlikClient
      
    3. 将您的根 CA 添加到信任库

      keytool -importcert \
          -keystore truststore.pfx -storepass PASSWORD \
          -file root.pem -noprompt \
          -alias qlikServerCACert
      

    请注意,在上述命令中,我们对密钥库和信任库使用相同的 PASSWORD。您也可以使用不同的密码。另请注意,您必须为添加到信任库的每个项目指定一个别名。

    如果您希望您的信任库信任系统中所有可用的 cacert,请在第 2 步或第 3 步添加-trustcacerts 选项。

    您可以使用以下命令列出您的信任库的内容

    keytool -list -keystore truststore.pfx -storepass PASSWORD
    

    在您的应用程序中使用信任库

    拥有信任库后,您需要将其加载到您的应用程序中。假设您有一个常量 KEYSTORE_PATH 保存信任库的路径,keyStorePass 保存密码,将信任库文件读入 KeyStore

    private KeyStore readStore() {
      try (InputStream keyStoreStream = new FileInputStream(KEYSTORE_PATH)) {
        KeyStore keyStore = KeyStore.getInstance("PKCS12"); // or "JKS"
        keyStore.load(keyStoreStream, keyStorePass.toCharArray());
        return keyStore;
      } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
      }
    }
    

    创建自定义SSLContext 和自定义HttpClient

    final KeyStore truststore = readStore();
    
    final SSLContext sslContext;
    try {
      sslContext = SSLContexts.custom()
          .loadTrustMaterial(truststore, new TrustAllStrategy())
          .loadKeyMaterial(truststore, keyStorePass.toCharArray(), (aliases, socket) -> "qlikClient")
          .build();
    } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException | UnrecoverableKeyException e) {
      throw new RuntimeException("Failed to read keystore", e);
    }
    final CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
    

    您现在可以使用此HttpClient 向您的 API 发出请求。

    HttpResponse response = httpClient.execute(new HttpGet("https://sense-gcp-central1eu.net:4242/qrs/app/full"));
    

    或者,如果您使用的是 OpenUnirest/unirest-java 库,您可以将 Unirest 配置为使用您的自定义 HttpClient

    Unirest.config().httpClient(httpClient);
    HttpResponse<JsonNode> response = Unirest.get("https://sense-gcp-central1eu.net:4242/qrs/app/full").asJson();
    

    参考文献

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    相关资源
    最近更新 更多