1. 概述

网络安全在现代应用程序中扮演着重要角色,客户端与服务器之间通过HTTP通讯并不安全,对于生成环境上的应用我们应该通过TSL协议开启HTTPS。本教程,我们将讨论如何在Spring Boot中启用TLS技术。

2. TLS 协议

HTTPS 即 HTTP over TLS。TLS为客户端与服务器之间的数据传输提供安全保护。安全套接层(SSL)和传输层安全性协议(TLS)通常可以互换使用,但它们并不相同,SSL是TLS的前身。 TLS 分为单向或双向认证。

2.1. TLS单向认证

在单向TLS中, 只有客户端验证服务器以确保客户端从受信任的服务器上接收数据。客户端共享服务器的公共证书。

2.2. TLS双向认证

双向 TLS (Mutual TLS,mTLS)中, 客户端和服务器端都需要验证对方的身份,以保证参与的双方都是可信的。mTLS中双方共享自己的公共证书。

3. Spring Boot 中配置 TLS

3.1. 生成 Key Pair

要开启TLS,我们需要先创建公钥/私钥对。为此,我们将使用keytool这个工具。Java发行版中已经默认包含了keytool 这个命令行工具。下面我们使用 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 配置 TLS

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

# enable/disable https
server.ssl.enabled=true
# keystore format
server.ssl.key-store-type=PKCS12
# keystore location
server.ssl.key-store=classpath:keystore/keystore.p12
# keystore password
server.ssl.key-store-password=changeit

在配置 SSL 协议时,设置使用 TLS,版本为 1.2:

# SSL protocol to use
server.ssl.protocol=TLS
# Enabled SSL protocols
server.ssl.enabled-protocols=TLSv1.2

然后启动Spring Boot,验证是否配置成功:

3.3. Spring 配置 mTLS

要启用mTLS,我们需要设置 client-auth 属性值为need

server.ssl.client-auth=need

need 表示强制开启客户端身份验证。这意味着客户端和服务器都必须共享他们的公共证书。为了在 Spring Boot 应用程序中存储客户端的公共证书,我们需要在 application.properties 中配置truststore文件路径:

#trust store location
server.ssl.trust-store=classpath:keystore/truststore.p12
#trust store password
server.ssl.trust-store-password=changeit

trust-store文件包含证书颁发机构列表,这些证书颁发机构受机器信任以进行 SSL 服务器身份验证。 trust-store-password是访问truststore文件的密码。

4. Tomcat 配置 TSL

Tomcat默认没有开启HTTPS,需要修改server.xm配置文件:

<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 接口

使用curl工具请求REST API:

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

因为我们没加https,会报错:

Bad Request
This combination of host and port requires TLS.

需要将http改为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. 总结

为了保证数据安全传输,TSL支持单向和双向认证两种实现方式。本文我们描述了如何在Spring Boot 以及Tomcat中配置TLS。

惯例本文中的示例源码存放在GitHub上。