簡體   English   中英

如何在客戶端 java 應用程序中使用客戶端證書?

[英]How do I use client certificates in a client java application?

這是一個我花了很長時間才弄明白的話題。 零散的信息零散,必須將所有內容放在一起。 我希望通過這篇文章,我可以幫助其他人快速組裝一個可行的解決方案。


我有一個client-cert.pemclient-key.pem和一個root.pem文件,我需要在我的 Java 客戶端中使用它們來訪問遠程 REST API。

我如何將它們 package 放入信任庫並使用它們撥打 API 電話?

為了將您的證書加載到您的應用程序中,您需要將它們打包到一個信任庫中。

創建信任庫

給定 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 您也可以使用不同的密碼。 另請注意,您必須為添加到信任庫的每個項目指定一個別名。

如果您希望信任庫信任系統中可用的所有 cacerts,請將-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();

參考

我知道這是一個老問題,但我發現你的問題有問題。
您的客戶端使用信任庫來列出它可以信任的遠程服務器。
如果您擁有並想使用的證書/密鑰是為您自己的 java 客戶端准備的,您應該將它們包含在您的密鑰庫中,而不是信任庫中。
這是您的客戶端將使用的存儲,以防遠程服務器要求您的客戶端對自己進行身份驗證。

除了已經給出的答案之外,如果您使用 spring 引導和 resttemplate 作為 http 客戶端實現,您可以在應用程序屬性中使用通過這樣做創建的密鑰庫:

server:
  ssl:
    enabled: true
    key-alias: <<app-client-alias>>
    key-store: <<path_to_your_keystore>>
    key-store-password: <<PASSWORD>>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM