繁体   English   中英

如何在 Spring Boot 应用程序中使用 SSL 证书调用远程 API

[英]How to use SSL Certificates in Spring Boot application to call remote API

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

我有一个certificate.pemkey.pem 我需要在我的 Java 客户端中使用它们来使用 JERSEY 客户端访问远程 REST API。

到目前为止我尝试过的事情:

将 pem 文件转换为 JKS。

openssl pkcs12 -export -in certificate.pem -inkey key.pem -out client.jks -passout pass:CLIENT -name myClient

添加到信任库

keytool -importkeystore -destkeystore truststore.jks -deststoretype JKS -deststorepass CLIENT -srckeystore pathtoJKS://client.jks -srcstorepass CLIENT -srcstoretype JKS

添加的属性如下

-Djavax.net.ssl.keyStore=client.jks
-Djavax.net.ssl.keyStorePassword=CLIENT
-Djavax.net.ssl.trustStore=truststore.jks
-Djavax.net.ssl.trustStorePassword=CLIENT

但出于某种原因,远程 API 仍然认为,我没有发送正确的证书。

有人可以帮助我这里缺少什么吗?

编辑:-添加了 HTTP 客户端的代码。

String keyStorePath = "client.jks"; // File is present in main/resources folder
String trustStorePath = "truststore.jks"; // File is present in main/resources folder

char[] keyStorePassword = "CLIENT".toCharArray();
char[] trustStorePassword = "CLIENT".toCharArray();

KeyStore keyStore = KeyStore.getInstance("JKS");
KeyStore trustStore = KeyStore.getInstance("JKS");

try(InputStream keyStoreInputStream = Application.class.getClassLoader().getResourceAsStream(keyStorePath);
    InputStream trustStoreInputStream = Application.class.getClassLoader().getResourceAsStream(trustStorePath)) {

    Objects.requireNonNull(keyStoreInputStream);
    Objects.requireNonNull(trustStoreInputStream);

    keyStore.load(keyStoreInputStream, keyStorePassword);
    trustStore.load(trustStoreInputStream, trustStorePassword);
}

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyStorePassword);
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(keyManagers,trustManagers, new java.security.SecureRandom());

Client client = ClientBuilder.newBuilder()
    .sslContext(sslcontext)
    .hostnameVerifier(new TrustAllHostNameVerifier())
    .build();

请与我们分享您的源代码,因为追踪您当前面临的问题是有问题的。 乍一看,您的配置文件很好。 但是,您可以进行一些小的改进:

  • 确保在运行时定义了javax.net.ssl
  • 尝试指定绝对路径

我不太确定以这种方式添加密钥库/信任库属性是否有效。 我习惯在创建实例时直接配置客户端配置,这肯定有效。

以下是 Jersey SSL 客户端配置示例:

SSLFactory sslFactory = SSLFactory.builder()
    .withIdentityMaterial("client.jks", "CLIENT".toCharArray())
    .withTrustMaterial("truststore.jks", "CLIENT".toCharArray())
    .build();

Client client = ClientBuilder.newBuilder()
    .sslContext(sslFactory.getSslContext())
    .hostnameVerifier(sslFactory.getHostnameVerifier())
    .build();

Jersey 需要配置的 SSLContext 实例。 上面的例子使用了SSLContext Kickstart 中的SSLFactory,它由我维护。 还有其他方法可以创建 SSLContext 的实例,请参阅此处了解我知道的所有可能方法: Mutual Authentication in Scala with Akka

你能试试上面的代码片段并把它的结果放在这里吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM