1. 概述

在本教程中,我们将学习如何在 Spring Boot 应用中启用 HTTPS。为此,我们会先生成一个自签名证书,并配置一个简单的示例应用。

如果你对 Spring Boot 项目还不太熟悉,可以参考这里的一系列资源。

2. 生成自签名证书

开始之前,我们需要先生成一个自签名证书。常用的证书格式有两种:

  • PKCS12: Public Key Cryptographic Standards,是一种受密码保护的格式,可以包含多个证书和密钥,属于业界通用标准。
  • JKS: Java KeyStore,与 PKCS12 类似,但它是 Java 专有的格式,仅限于 Java 环境中使用。

我们可以使用命令行工具 keytool 或 OpenSSL 来生成证书。Keytool 是 JDK 自带的工具,而 OpenSSL 可以从这里下载。

推荐使用 keytool 工具进行演示操作。

2.1. 生成密钥库

接下来我们创建一组加密密钥,并将它们存储在一个密钥库(keystore)中。

生成 PKCS12 格式的密钥库,可以使用如下命令:

keytool -genkeypair -alias baeldung -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore baeldung.p12 -validity 3650

同一个 keystore 文件中可以保存多个密钥对,每个通过唯一的 alias(别名)来区分。

如果想生成 JKS 格式的 keystore,可以使用以下命令:

keytool -genkeypair -alias baeldung -keyalg RSA -keysize 2048 -keystore baeldung.jks -validity 3650

⚠️ 建议优先使用 PKCS12 格式,这是行业标准格式。
如果你已经有了 JKS 格式的 keystore,可以通过下面的命令将其转换为 PKCS12:

keytool -importkeystore -srckeystore baeldung.jks -destkeystore baeldung.p12 -deststoretype pkcs12

执行时需要输入源 keystore 的密码,并设置新的密码。这些信息后续会用到。

3. 在 Spring Boot 中启用 HTTPS

Spring Boot 提供了一组声明式的 server.ssl.* 配置属性。我们将在示例应用中使用这些属性来配置 HTTPS。

我们从一个简单的 Spring Boot 应用入手,该应用包含一个由 */welcome* 接口处理的欢迎页面,并且已经引入了 Spring Security

然后我们将上一步生成的文件 "baeldung.p12" 复制到项目的 "src/main/resources/keystore" 目录下。

3.1. 配置 SSL 属性

现在我们来配置 SSL 相关的属性:

# 密钥库的格式。如果是 JKS 文件,则设置为 JKS
server.ssl.key-store-type=PKCS12
# 包含证书的密钥库路径
server.ssl.key-store=classpath:keystore/baeldung.p12
# 生成证书时使用的密码
server.ssl.key-store-password=password
# 映射到证书的别名
server.ssl.key-alias=baeldung

因为我们使用的是启用了 Spring Security 的应用,所以还需要配置只接受 HTTPS 请求:

server.ssl.enabled=true

4. 调用 HTTPS 接口

应用中已启用 HTTPS,接下来我们切换到客户端视角,看看如何调用带有自签名证书的 HTTPS 接口。

首先,我们要创建一个信任库(trust store)。由于我们已经生成了一个 PKCS12 文件,可以直接作为信任库使用。定义如下属性:

# 信任库路径
trust.store=classpath:keystore/baeldung.p12
# 信任库密码
trust.store.password=password

接着准备一个 SSLContext 并创建自定义的 RestTemplate 实例:

RestTemplate restTemplate() throws Exception {
    SSLContext sslContext = new SSLContextBuilder()
      .loadTrustMaterial(trustStore.getURL(), trustStorePassword.toCharArray())
      .build();
    SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
    HttpClient httpClient = HttpClients.custom()
      .setSSLSocketFactory(socketFactory)
      .build();
    HttpComponentsClientHttpRequestFactory factory = 
      new HttpComponentsClientHttpRequestFactory(httpClient);
    return new RestTemplate(factory);
}

为了演示方便,我们让 Spring Security 允许所有请求访问:

public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { 
    http.authorizeRequests() 
      .antMatchers("/**") 
      .permitAll(); 
    return http.build(); 
}

最后就可以调用 HTTPS 接口了:

@Test
public void whenGETanHTTPSResource_thenCorrectResponse() throws Exception {
    ResponseEntity<String> response = 
      restTemplate().getForEntity(WELCOME_URL, String.class, Collections.emptyMap());

    assertEquals("<h1>Welcome to Secured Site</h1>", response.getBody());
    assertEquals(HttpStatus.OK, response.getStatusCode());
}

5. 总结

本文我们学习了如何在 Spring Boot 应用中生成自签名证书并启用 HTTPS,还介绍了如何通过客户端调用 HTTPS 接口的方式验证配置是否生效。

最后别忘了,在运行示例代码前,请取消注释 pom.xml 中的如下配置项:

<start-class>com.baeldung.ssl.HttpsEnabledApplication</start-class>

原始标题:HTTPS using Self-Signed Certificate in Spring Boot | Baeldung