在Java HTTP请求中包含.pem证书

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Java HTTP请求中包含.pem证书相关的知识,希望对你有一定的参考价值。

我目前能够使用以下curl命令访问需要客户端证书的Web服务:

curl -k -v --cert ./certificate.pem https://api.com/unit

如何在Java应用程序中发出此请求?

请注意,我需要-k标志,它允许curl进行“不安全”的SSL连接。这也需要在Java应用程序中完成。

答案

下面的代码提供了一个“sendSSLRequest”方法,该方法使用客户端SSL身份验证发送HTTP GET请求。

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.client.methods.HttpGet;

public class SSLExample {

   private final static String ENDPOINT_URL = "https://api.com/unit";

   public void sendSSLRequest() {

      final SSLContext sslContext = SSLContextLoader.initSSLContext();

      final HttpClient client = HttpClients.custom()
                                    .setSSLContext(sslContext)
                                    .build();
      final HttpGet request = new HttpGet(ENDPOINT_URL);

      try {
         client.execute(request);
      } catch (final IOException e) {
         //do some exception handling...
      }
   }
}

现在,SSLContext:你需要在某个地方初始化它。下面的“initSSLContext”方法将从给定的密钥库加载密钥材料,并从给定的信任库中加载信任材料(要信任的证书)。

public class SSLContextLoader {

   private final static String clientKeyStorePath = "/path/to/client/keystore";
   private final static String trustStorePath = "/path/to/truststore";
   private final static String clientKeyStorePassword = "/password/for/client/keystore";
   private final static String trustStorePassword = "/password/for/truststore";
   private final static String keyPassword = "/passphrase/for/private/key";

   public static SSLContext initSSLContext () {
      try {
         final KeyStore clientKeystore = KeyStore.getInstance("JKS");
         clientKeystore.load(new FileInputStream(clientKeyStorePath), clientKeyStorePassword.toCharArray());
         final KeyStore trustStore = KeyStore.getInstance("JKS");
         trustStore.load(new FileInputStream(trustStorePath), trustStorePassword.toCharArray());

         final SSLContext sslContext = SSLContexts.custom()
            .loadTrustMaterial(trustStore, null)
            .loadKeyMaterial(clientKeystore, keyPassword.toCharArray())
            .build();

         return sslContext;
      } catch (KeyStoreException e) {
         e.printStackTrace();
      } catch (CertificateException e) {
         e.printStackTrace();
      } catch (NoSuchAlgorithmException e) {
         e.printStackTrace();
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } catch (UnrecoverableKeyException e) {
         e.printStackTrace();
      } catch (KeyManagementException e) {
         e.printStackTrace();
      }
     return null;
   }
}

关于-k选项,我邀请您查看以下问题/答案:Trusting all certificates using HttpClient over HTTPS

另一答案

此问题的最终解决方案是将服务器的证书包含在Java信任库中。

要下载并导入服务器的证书,我使用了来自GitHub的InstallCert Java代码

然后在系统属性中定义keyStoretrustStore,如下所示:

-Djavax.net.ssl.keyStore=/home/wildfly/key.pfx
-Djavax.net.ssl.keyStorePassword=xxxx
-Djavax.net.ssl=trustStore=$JAVA_HOME/jre/lib/security/cacerts
-Djavax.net.ssl.trustStorePassword=xxxx
-Djavax.net.ssl.keyStoreType=PKCS12"

以上是关于在Java HTTP请求中包含.pem证书的主要内容,如果未能解决你的问题,请参考以下文章

证书格式转换

使用 openssl 以编程方式提取 pem 证书信息

Spring Security SAML 请求在证书中包含 ^M 个字符

在代码片段中包含类型转换

K8S二进制部署(更新中)

安装Https证书