领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多在 Spring Boot 3.2.0 中,我们增加了嵌入式 Web 服务器热加载 SSL 证书和密钥的功能。这意味着您可以在不重启应用程序的情况下轮换 SSL 信任材料。Tomcat 和 Netty 嵌入式 Web 服务器支持热加载。
让我们看看它是如何工作的!
首先,我们将使用 OpenSSL 创建我们的 SSL 私钥和匹配的证书
mkdir certs
cd certs
openssl req -x509 -subj "/CN=demo-cert-1" -keyout demo.key -out demo.crt -sha256 -days 365 -nodes -newkey rsa
这将在 certs/demo.key
中创建一个存储的私钥,并在 certs/demo.crt
中创建一个具有公用名称“demo-cert-1”的匹配(自签名)证书。
现在,我们正在使用“Spring Web”依赖项创建一个新的 Spring Boot 3.2.0 应用程序,该依赖项默认使用 Tomcat Web 服务器,并使用我们最喜欢的网站 start.spring.io。
在应用程序配置中,我们添加了以下内容
spring.ssl.bundle.pem:
demo:
reload-on-update: true
keystore:
certificate: "certs/demo.crt"
private-key: "certs/demo.key"
这使用名称“demo”配置了一个 SSL 捆绑包 以及我们生成的证书和私钥。reload-on-update: true
配置指示 Spring Boot 在后台监视文件,并在文件更改时触发重新加载。
现在,我们正在配置 Web 服务器以使用该捆绑包并在端口 8443 上接受连接
server.ssl.bundle: "demo"
server.port: 8443
我们还添加了一个简单的控制器,它响应一个简单的“Hello World”
@RestController
class DemoController {
@GetMapping(path = "/", produces = MediaType.TEXT_PLAIN_VALUE)
String helloWorld() {
return "Hello World";
}
}
当我们启动应用程序时,我们在日志中看到类似以下内容,这确认它在使用 HTTPS 的端口 8443 上启动。
INFO 82407 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8443 (https)
现在,我们可以使用 curl 发出我们的第一个请求
$ curl --insecure https://127.0.0.1:8443/
Hello World%
万岁,它起作用了!我们必须传递 --insecure
,因为 SSL 证书是自签名的,并且 curl 不信任它。
让我们将 curl 切换到详细模式以获取有关发生的 SSL 握手的一些信息
$ curl --verbose --insecure https://127.0.0.1:8443/
* Trying 127.0.0.1:8443...
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
* subject: CN=demo-cert-1
* start date: Nov 2 09:22:53 2023 GMT
* expire date: Nov 1 09:22:53 2024 GMT
* issuer: CN=demo-cert-1
* SSL certificate verify result: self-signed certificate (18), continuing anyway.
* using HTTP/1.x
> GET / HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/8.0.1
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/1.1 200
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 11
< Date: Thu, 02 Nov 2023 09:33:37 GMT
<
* Connection #0 to host localhost left intact
Hello World
在 subject: CN=demo-cert-1
行中,您可以看到证书的公用名称是“demo-cert-1”,这在后面很重要。
让我们尝试通过使用 OpenSSL 生成新的私钥和证书(覆盖旧文件)来进行热加载
cd certs
openssl req -x509 -subj "/CN=demo-cert-2" -keyout demo.key -out demo.crt -sha256 -days 365 -nodes -newkey rsa
这次,我们的证书的公用名称为“demo-cert-2”。
一段时间后,您将在日志中看到类似以下内容
INFO 83162 --- [-bundle-watcher] o.a.t.util.net.NioEndpoint.certificate : Connector [https-jsse-nio-8443], TLS virtual host [_default_], certificate type [UNDEFINED] configured from keystore [/home/xxx/.keystore] using alias [tomcat] with trust store [null]
这是一种复杂的说法,表明 Tomcat 已重新加载私钥和证书。
现在,我们可以使用 curl 验证是否使用了新证书
$ curl --verbose --insecure https://127.0.0.1:8443/
* Trying 127.0.0.1:8443...
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server did not agree on a protocol. Uses default.
* Server certificate:
* subject: CN=demo-cert-2
* start date: Nov 2 09:37:46 2023 GMT
* expire date: Nov 1 09:37:46 2024 GMT
* issuer: CN=demo-cert-2
* SSL certificate verify result: self-signed certificate (18), continuing anyway.
* using HTTP/1.x
> GET / HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/8.0.1
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
< HTTP/1.1 200
< Content-Type: text/plain;charset=UTF-8
< Content-Length: 11
< Date: Thu, 02 Nov 2023 09:39:47 GMT
<
* Connection #0 to host localhost left intact
Hello World
subject: CN=demo-cert-2
行验证了是否使用了新证书。万岁,取得了巨大的成功!
概括一下:我们创建了一个 SSL 私钥和证书,然后我们配置 Spring Boot 以使用它并监视更改。当私钥和证书更改时,Spring Boot 会重新加载它们,并且它们将在不重启应用程序的情况下使用。这难道不酷吗?!
顺便说一下,如果您想知道已经存在的连接会发生什么:它们将继续使用旧证书,但所有新连接都将使用新证书。
我们希望此功能简化您的操作。您可以通过测试 Spring Boot 3.2.0-RC2 来尝试一下。如果您有任何增强想法或发现错误,请不要犹豫,在 我们的跟踪器 上提交问题。