首页 > 解决方案 > 使用 Spring RestTemplate 验证 HTTPS REST 调用的证书和主机名

问题描述

我有一个 Spring Boot 微服务,我试图在其中调用一个公开 HTTPS REST 端点(TLS v1.2)的外部服务器。我已获得 .pem 格式的服务器端证书。

我想使用 RestTemplate 来实现这个调用,并使用提供的证书并在调用过程中验证主机名。

我试图用谷歌搜索,所有搜索结果都试图忽略证书和主机名。

我可以有一个示例代码片段来正确实现它吗?

标签: spring-boothttpsssl-certificateresttemplatetls1.2

解决方案


在对不同的博客和 stackoverflow 线程进行了一些挖掘之后,以下内容对我有用:

创建休息模板:

KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(ResourceUtils.getFile(clientKeyPath)), "".toCharArray());

SSLContext sslContext = SSLContextBuilder
                .create()
                .loadKeyMaterial(keyStore, null)
                .loadTrustMaterial(ResourceUtils.getFile(keystorePath), keystorePassword.toCharArray())
                .build();

SSLConnectionSocketFactory sslConnectionSocketFactory = new  SSLConnectionSocketFactory(sslContext, new CustomHostnameVerifier());

HttpClient client = HttpClients
                .custom()
                .setSSLSocketFactory(sslConnectionSocketFactory)
                .build();

HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();

requestFactory.setHttpClient(client);

RestTemplate sslRestTemplate = new RestTemplate(requestFactory);

CustomHostnameVerifier 的实现:

@Component
public class CustomHostnameVerifier implements HostnameVerifier {

    @Value("${dns.name}")
    private String dnsName;

    @Override
    public boolean verify(String hostname, SSLSession session) {
        return hostname.equals(dnsName);
    }
}

推荐阅读