Spring Boot 配置 TLS

1、概览

安全通信在现代应用中发挥着重要作用。客户端和服务器之间通过普通 HTTP 进行的通信并不安全。对于生产级的应用,应该在应用中通过 TLS(传输层安全)协议启用 HTTPS。

本文将带你了解如何在 Spring Boot 应用中启用 TLS。

2、TLS 协议

TLS 为客户端和服务器之间的数据传输提供保护,是 HTTPS 协议的关键组成部分。安全套接字层(SSL)和 TLS 经常被互换使用,但两者并不相同。事实上,TLS 是 SSL 的继承者。TLS 可以单向或双向实现。

2.1、单向 TLS

在单向 TLS 中,只有客户端对服务器进行验证,以确保从受信任的服务器接收数据。为实现单向 TLS,服务器会与客户端共享其公共证书。

2.2、双向 TLS

在双向 TLS 或相互 TLS(mTLS)中,客户端和服务器都要相互验证,以确保通信双方都是可信的。在实现 mTLS 时,双方要共享各自的公开证书。

3、Spring Boot 配置 TLS

3.1、生成密钥对

要启用 TLS,需要创建一对公钥/私钥。为此,可以使用 keytool 命令行工具,它默认 随 Java 发行版一起提供。

使用 keytool 生成一对密钥,并将其存储到 keystore.p12 文件中:

keytool -genkeypair -alias baeldung -keyalg RSA -keysize 4096 \
  -validity 3650 -dname "CN=localhost" -keypass changeit -keystore keystore.p12 \
  -storeType PKCS12 -storepass changeit

keystore 文件可以是不同的格式。最常用的两种格式是 Java KeyStore (JKS) 和 PKCS#12。JKS 是 Java 特有的格式,而 PKCS#12 是一种行业标准格式,属于 公钥加密标准(PKCS)定义的标准系列。

3.2、在 Spring Boot 中配置 TLS

先从配置单向 TLS 开始。在 application.properties 文件中配置 TLS 相关属性:

# 启用/禁用 https
server.ssl.enabled=true
# keystore 格式
server.ssl.key-store-type=PKCS12
# keystore 位置
server.ssl.key-store=classpath:keystore/keystore.p12
# keystore 密码
server.ssl.key-store-password=changeit

配置 SSL 协议,指定要使用 TLS,并告诉服务器使用 TLS 1.2:

# 使用的 SSL 协议
server.ssl.protocol=TLS
# 启用 SSL 协议
server.ssl.enabled-protocols=TLSv1.2

只需运行 Spring Boot 应用,即可验证是否运行正常:

tls 日志

3.3、在 Spring Boot 中配置 mTLS

设置 server.ssl.client-auth 的值为 need 来启用 mTLS。

server.ssl.client-auth=need

当指定 need 值时,客户端认证是必需的。这意味着客户端和服务器都必须共享它们的公共证书。使用 truststore 文件将客户端的证书存储在 Spring Boot 应用中,并在 application.properties 文件中进行配置:

# trust store 路径
server.ssl.trust-store=classpath:keystore/truststore.p12
# trust store 密码
server.ssl.trust-store-password=changeit

truststore 的路径是一个文件,其中包含机器在 SSL 服务器身份验证中信任的证书颁发机构列表。truststore 密码是用于访问 truststore 文件的密码。

4、在 Tomcat 中配置 TLS

默认情况下,Tomcat 启动时使用的是不带任何 TLS 功能的 HTTP 协议。要在 Tomcat 中启用 TLS,需要配置 server.xml 文件:

<Connector
  protocol="org.apache.coyote.http11.Http11NioProtocol"
  port="8443" maxThreads="200"
  scheme="https" secure="true" SSLEnabled="true"
  keystoreFile="${user.home}/.keystore" keystorePass="changeit"
  clientAuth="false" sslProtocol="TLS" sslEnabledProtocols="TLSv1.2"/>

如果需要启用 mTLS,可设置 clientAuth="true".

5、调用 HTTPS API

使用 curl 工具调用 REST API:

curl -v http://localhost:8443/baeldung

由于没有指定 https,因此会报错:

Bad Request
This combination of host and port requires TLS.

使用 https 协议进行访问可以解决这个问题:

curl -v https://localhost:8443/baeldung

然而,这又报了另一个错:

SSL certificate problem: self signed certificate

当使用自签名证书时,就会出现这种情况。要解决这个问题,必须在客户端请求中使用服务器证书。首先,从服务器 keystore 文件中复制服务器证书 baeldung.cer。然后在 curl 请求中使用 --cacert 选项指定服务器证书:

curl --cacert baeldung.cer https://localhost:8443/baeldung

6、总结

本文介绍了 TLS 的概念和作用,以及如何在 Spring Boot 中通过 application.properties 配置单向和双向的 TSL。最后还介绍了如何在 Tomcat 中配置 TSL。

另外,Spring Boot 3 开始,提供给了一个名为 “SSL Bundle” 组件,这使得在 Spring Boot 中配置 SSL 更加的简单、方便。你可以参考如下博客:


Ref:https://www.baeldung.com/spring-tls-setup