繁体   English   中英

在对外部服务进行 REST API 调用时如何包含客户端证书 - Spring Boot?

[英]How to include client certificate when making REST API call to an external service - Spring Boot?

我试图通过在 Spring Boot 中包含 pfx 文件来调用外部 API 端点,但我得到:

Request processing failed; nested exception is org.springframewrk.web.client.ResourceAccessException: I/O error...
Connection reset; nested excrption is java.net.SocketExceptin: Connection reset 

我也尝试将属性添加到 application.properties 中,但也没有工作。

我遵循的代码: 如何在 spring 引导休息模板中使用 .pfx 证书和密码调用安全休息 api? 哪个不起作用我也尝试了微小的更改,但也不起作用

它在包含 pfx 文件的邮递员中工作正常。

为 Http 客户端配置 ssl 可能很棘手,但是当您知道如何去做时,它就很简单了。 在您的情况下,您需要做的是将客户端证书作为KeyManager加载到SSLContext ,并将受信任的服务器证书作为TrustManager加载到SSLContext 我在您的评论中看到您正在使用 Apache 的 closableHttpClient。 Apache 有 4 个 http 客户端,我不清楚您使用的是哪一个,所以我在这里发布了所有四个示例:

SSL上下文

首先让我们创建 SSLContext,稍后我们将使用它来配置 http 客户端:

import javax.net.ssl.*;
import java.io.File;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Objects;

class SslExample {

    public static void main(String[] args) throws Exception {

        //Traditional flow of creating sslContext
        String keyStorePath = "keystore.p12";
        String trustStorePath = "truststore.p12";

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

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

        try(InputStream keyStoreInputStream = SslExample.class.getClassLoader().getResourceAsStream(keyStorePath);
            InputStream trustStoreInputStream = SslExample.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, null);

        //Alternative - Creating sslContext with Apache SSLContextBuilder
        SSLContext sslContext1 = SSLContextBuilder.create()
                .loadKeyMaterial(new File("keystore.p12"), "secret".toCharArray(), "secret".toCharArray())
                .loadTrustMaterial(new File("truststore.p12"), "secret".toCharArray())
                .build();
    }

}

Apache 4 的 HttpClient

LayeredConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);

CloseableHttpClient client = HttpClients.custom()
    .setSSLSocketFactory(socketFactory)
    .build();

Apache 4 的异步 HttpClient

CloseableHttpAsyncClient client = HttpAsyncClients.custom()
    .setSSLContext(sslContext)
    .build();

client.start();

Apache 5 的 HttpClient

LayeredConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);

HttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
    .setSSLSocketFactory(socketFactory)
    .build();

CloseableHttpClient client = HttpClients.custom()
    .setConnectionManager(connectionManager)
    .build();

用于 Apache 5 的异步 HttpClient

AsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create()
        .setTlsStrategy(new BasicClientTlsStrategy(sslContext))
        .build();

CloseableHttpAsyncClient client = HttpAsyncClients.custom()
        .setConnectionManager(connectionManager)
        .build();

client.start();

您可以重试上述配置并在此处分享您的结果吗?

您可以将客户端证书放在 SpringBoot 应用程序资源文件夹中,然后设置javax.net.ssl.keyStore属性。 然后,一旦你想发出请求,你可以创建一个自定义的HttpClient并设置SSLContext如下:

public static void main(String[] args) throws Exception {
    SpringApplication.run(DemoApplication.class, args);
    System.setProperty("javax.net.ssl.keyStore", new ClassPathResource("example.p12").getFile().getAbsolutePath());

    CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(SSLContext.getDefault()).build();

    httpClient.execute(
            new HttpGet("https://prod.idrix.eu/secure/"));
}

暂无
暂无

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

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