如何在客户端Java应用程序中使用客户端证书?

时间:2018-12-10 16:20:22

标签: java https certificate keystore

这个话题花了我很多时间弄清楚。零星的信息零散,人们必须将所有信息汇总在一起。我希望通过这篇文章可以帮助其他人迅速收集一个可行的解决方案。


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

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

1 个答案:

答案 0 :(得分:2)

要将证书加载到应用程序中,您需要将其打包到信任库中。

创建信任库

给出了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。您也可以使用其他密码。还要注意,您必须为添加到信任库的每个项目指定一个别名。

如果您希望信任库信任系统中所有可用的证书,请将-trustcacerts选项添加到步骤2或3。

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

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();

参考