1、概览 {#1概览}
在本教程中,我们将学习如何给 RestTemplate
配置 SSL 证书来访问 HTTPS 加密的 REST 服务。
2、设置 {#2设置}
要确保 REST 服务的安全,我们需要使用证书和由证书生成的 Keystore。
证书可以从 CA 获取,在本文的示例中,使用的是自签名证书。
我们将使用 Spring 的 RestTemplate
来访问 HTTPS REST 服务。
首先,让我们创建一个 Controller 类 WelcomeController
和一个 /welcome
端点(返回一个简单的字符串响应):
@RestController
public class WelcomeController {
@GetMapping(value = "/welcome")
public String welcome() {
return "Welcome To Secured REST Service";
}
}
然后,在 src/main/resources
文件夹中添加我们的 keystore:
src/main/resources
|-keystore
|-baeldung.p12
接下来,在 application.properties
文件中添加与 Keystore 相关的属性:
server.port=8443
server.servlet.context-path=/
# keystore 的格式
server.ssl.key-store-type=PKCS12
# 包含证书的 keystore 的路径
server.ssl.key-store=classpath:keystore/baeldung.p12
# 生成证书时使用的密码
server.ssl.key-store-password=password
# 证书的别名
server.ssl.key-alias=baeldung
现在我们可以通过以下端点访问 REST 服务:https://localhost:8443/welcome
3、访问 Secured REST 服务 {#3访问-secured-rest-服务}
Spring 提供了一个方便的 RestTemplate
类来访问 REST 服务。
访问简单的 REST 服务很简单,但在访问 Secured REST 服务时,我们需要根据服务使用的证书/Keystore 来自定义 RestTemplate
。
接下来,创建一个简单的 RestTemplate
对象,添加所需的证书/Keystore。
3.1、创建 RestTemplate
{#31创建-resttemplate}
编写一个简单的 Controller,使用 RestTemplate
来调用 REST 服务:
@RestController
public class RestTemplateClientController {
private static final String WELCOME_URL = "https://localhost:8443/welcome";
@Autowired
private RestTemplate restTemplate;
@GetMapping("/welcomeclient")
public String greetMessage() {
String response = restTemplate.getForObject(WELCOME_URL, String.class);
return response;
}
}
如果运行代码并访问 /welcomeclient
端点,就会出现异常,因为找不到访问 Secured REST 服务的有效证书:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested
target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
接下来,我们看看如何解决这个错误。
3.2、配置 RestTemplate
以访问 HTTPS {#32配置-resttemplate-以访问-https}
访问 Secured REST 服务的客户端应用应在其 resources
文件夹中包含一个 Secure Keystore。此外,还需要对 RestTemplate
进行配置。
首先,在 /src/main/resources
文件夹中添加之前的 Keystore baeldung.p12
作为 truststore:
src/main/resources
|-keystore
|-baeldung.p12
接下来,需要在 application.properties
文件中添加 truststore
详情:
server.port=8082
# trust store 位置
trust.store=classpath:keystore/baeldung.p12
# trust store 密码
trust.store.password=password
最后,自定义 RestTemplate
,添加 truststore
:
@Configuration
public class CustomRestTemplateConfiguration {
@Value("${trust.store}")
private Resource trustStore;
@Value("${trust.store.password}")
private String trustStorePassword;
@Bean
public RestTemplate restTemplate() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException,
CertificateException, MalformedURLException, IOException {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(trustStore.getURL(), trustStorePassword.toCharArray()).build();
SSLConnectionSocketFactory sslConFactory = new SSLConnectionSocketFactory(sslContext);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConFactory).build();
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(requestFactory);
}
}
在 restTemplate()
放中。首先,我们使用 SSLContextBuilder
类的 build()
方法来创建一个表示 Secure Socket Protocol 实现的 SSLContext
对象。
我们使用 SSLContextBuilder
的 loadTrustMaterial()
方法将 keystore 文件和凭据加载到 SSLContext
对象中。
然后,我们通过加载 SSLContext
创建 SSLConnectionSocketFactory
,这是一个用于 TSL 和 SSL 连接的分层 Socket Factory。这一步的目的是验证服务器是否使用了我们在上一步中加载的受信任证书列表,即对服务器进行身份验证。
现在,我们可以使用自定义的 RestTemplate
在端点 http://localhost:8082/welcomeclient
中访问 Secured REST 服务,并返回结果:
$ curl localhost:8082/welcomeclient
Welcome To Secured REST Service
4、总结 {#4总结}
在本文中,我们学习了如何给 RestTemplate
配置 SSL 证书来访问 Secured REST 服务。
参考:https://www.baeldung.com/spring-resttemplate-secure-https-service