问题描述
我需要从我的spring boot应用程序中调用一个外部安全的REST API(已启用ssl)。邮递员可使用.pfx证书和密码访问外部api。 现在,我想使用rest模板通过在每个请求上附加.pfx文件和密码来调用外部api。
我不知道如何使用pfx证书通过ssl进行剩余模板调用。任何帮助将不胜感激。
解决方法
您需要做的是配置其余模板的基础apache http客户端。下面是一个示例配置:
SSLContext sslContext = ...;
HttpClient httpClient = HttpClients.custom()
.setSSLContext(sslContext)
.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
有两个库提供了易于使用的实用程序/工厂/生成器类,以帮助您创建SSLContext。
可能还有许多其他提供类似功能的库,但是我只知道这三个。顺便说一下,sslcontext-kickstart是一个由我维护的库。
下面是加载密钥库和创建SSLContext的四种方法的概述。 Vanilla Java并使用这三个库。
import io.netty.handler.ssl.SslContextBuilder;
import nl.altindag.sslcontext.SSLFactory;
import org.apache.http.ssl.SSLContextBuilder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import javax.net.ssl.*;
import java.io.File;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.Objects;
class SslExample {
public static void main(String[] args) throws Exception {
//Traditional flow of creating sslContext
String keyStorePath = "keystore.pfx";
String trustStorePath = "truststore.pfx";
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("TLSv1.2");
sslContext.init(keyManagers,trustManagers,new SecureRandom());
//creating sslContext with Apache SSLContextBuilder
SSLContext sslContext1 = SSLContextBuilder.create()
.loadKeyMaterial(new File("keystore.pfx"),"secret".toCharArray(),"secret".toCharArray())
.loadTrustMaterial(new File("truststore.pfx"),"secret".toCharArray())
.build();
//creating sslContext with Jetty SslContextFactory
SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
sslContextFactory.setKeyStorePath("keystore.pfx");
sslContextFactory.setKeyStorePassword("secret");
sslContextFactory.setTrustStorePath("truststore.pfx");
sslContextFactory.setTrustStorePassword("secret");
sslContextFactory.start();
SSLContext sslContext2 = sslContextFactory.getSslContext();
//creating sslContext with sslcontext-kickstart
SSLFactory sslFactory = SSLFactory.builder()
.withIdentityMaterial("keystore.pfx","secret".toCharArray())
.withTrustMaterial("truststore.pfx","secret".toCharArray())
.build();
SSLContext sslContext3 = sslFactory.getSslContext();
}
}