1、概览 {#1概览}
安全通信在现代应用中发挥着重要作用。客户端和服务器之间通过普通 HTTP 进行的通信并不安全。对于生产级的应用,应该在应用中通过 TLS(传输层安全)协议启用 HTTPS。
本文将带你了解如何在 Spring Boot 应用中启用 TLS。
2、TLS 协议 {#2tls-协议}
TLS 为客户端和服务器之间的数据传输提供保护,是 HTTPS 协议的关键组成部分。安全套接字层(SSL)和 TLS 经常被互换使用,但两者并不相同。事实上,TLS 是 SSL 的继承者。TLS 可以单向或双向实现。
2.1、单向 TLS {#21单向-tls}
在单向 TLS 中,只有客户端对服务器进行验证,以确保从受信任的服务器接收数据。为实现单向 TLS,服务器会与客户端共享其公共证书。
2.2、双向 TLS {#22双向-tls}
在双向 TLS 或相互 TLS(mTLS)中,客户端和服务器都要相互验证,以确保通信双方都是可信的。在实现 mTLS 时,双方要共享各自的公开证书。
3、Spring Boot 配置 TLS {#3spring-boot-配置-tls}
3.1、生成密钥对 {#31生成密钥对}
要启用 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 {#32在-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 应用,即可验证是否运行正常:
3.3、在 Spring Boot 中配置 mTLS {#33在-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 {#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 {#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、总结 {#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