好的,我们开始今天的讲座:Spring Boot 3.2 SSL Bundles 配置 OCSP Stapling 与 TLS 1.3 会话恢复。
引言:SSL/TLS 安全的重要性
在现代网络应用中,SSL/TLS 安全至关重要。它不仅保护数据在传输过程中的机密性和完整性,还验证服务器的身份,防止中间人攻击。随着安全威胁的不断演变,我们需要持续关注和采用最新的安全技术。Spring Boot 3.2 引入的 SSL Bundles 提供了一种便捷的方式来配置 SSL/TLS,并支持 OCSP Stapling 和 TLS 1.3 会话恢复等高级特性。
1. SSL Bundles 简介
Spring Boot 3.2 引入的 SSL Bundles 是一种简化 SSL/TLS 配置的方式。它允许你将所有相关的 SSL/TLS 配置(例如证书、密钥、信任库等)集中管理,并通过一个逻辑名称引用它们。这大大简化了配置过程,并提高了可维护性。
2. 准备工作:生成证书与密钥
首先,我们需要生成 SSL 证书和密钥。可以使用 openssl 工具完成此操作。
-
生成私钥:
openssl genrsa -out key.pem 2048 -
创建证书签名请求 (CSR):
openssl req -new -key key.pem -out csr.pem在提示中,你需要提供一些信息,例如国家/地区、组织名称、通用名称 (Common Name, CN)。 Common Name 需要填写你的域名或者IP地址。
-
自签名证书(生产环境不建议使用,应使用权威CA机构签发的证书):
openssl x509 -req -days 365 -in csr.pem -signkey key.pem -out cert.pem这会创建一个有效期为 365 天的自签名证书
cert.pem。 -
生成PKCS12格式的证书库(用于Spring Boot配置)
openssl pkcs12 -export -inkey key.pem -in cert.pem -name "yourdomain" -out certificate.p12在提示中,你需要设置一个密码,这个密码将在 Spring Boot 配置中使用。
3. Spring Boot 项目配置
创建一个 Spring Boot 项目,并在 application.properties 或 application.yml 中配置 SSL Bundles。
-
application.yml 示例:
server: port: 8443 ssl: bundle: mybundle: key-store-type: PKCS12 key-store: classpath:certificate.p12 key-store-password: your_password key-alias: yourdomain key-password: your_password management: server: port: 9443 # 为management endpoint 配置单独的端口, 避免和业务端口冲突 ssl: bundle: managementbundle: key-store-type: PKCS12 key-store: classpath:certificate.p12 key-store-password: your_password key-alias: yourdomain key-password: your_password spring: ssl: bundle: pemfile: certificate: classpath:cert.pem private-key: classpath:key.pem application: name: ssl-bundle-demo在这个示例中,我们定义了一个名为
mybundle的 SSL Bundle。key-store-type指定密钥库类型为 PKCS12,key-store指定密钥库文件的路径,key-store-password指定密钥库密码,key-alias指定密钥别名,key-password指定密钥密码.managementbundle为 Spring Boot Actuator 的 management endpoint 配置了独立的SSL。pemfile配置则使用单独的证书和私钥文件,而不是密钥库。 -
配置 HTTPS Connector:
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatConfiguration { @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainerCustomizer() { return tomcatServletWebServerFactory -> { tomcatServletWebServerFactory.addConnectorCustomizers(connector -> { connector.setScheme("https"); connector.setSecure(true); connector.setPort(8443); // HTTPS 端口 connector.setAttribute("SSLEnabled", true); connector.setAttribute("sslImplementationName", org.apache.tomcat.util.net.openssl.OpenSSLImplementation.class.getName()); connector.setAttribute("sslProtocol", "TLSv1.3"); // 显式指定TLS协议版本 connector.setAttribute("SSLCertificateFile", "classpath:cert.pem"); // PEM 格式证书路径 connector.setAttribute("SSLCertificateKeyFile", "classpath:key.pem"); // PEM 格式私钥路径 }); }; } }这段代码使用
TomcatServletWebServerFactory来定制 Tomcat Connector,并设置 HTTPS 相关的属性。这里使用了PEM格式的证书和私钥,通过SSLCertificateFile和SSLCertificateKeyFile指定。sslProtocol显式指定了TLS版本为 TLSv1.3。
4. OCSP Stapling 配置
OCSP Stapling 是一种优化 SSL/TLS 握手过程的技术。它允许服务器定期从证书颁发机构 (CA) 获取证书的 OCSP (Online Certificate Status Protocol) 响应,并将响应“staple”到 SSL/TLS 握手过程中。这避免了客户端在每次连接时都向 CA 查询证书状态,从而提高了性能和隐私。
-
开启 OCSP Stapling:
在
application.yml中配置 OCSP Stapling。server: port: 8443 ssl: bundle: mybundle: key-store-type: PKCS12 key-store: classpath:certificate.p12 key-store-password: your_password key-alias: yourdomain key-password: your_password ocsp: enabled: true # 启用 OCSP Stapling management: server: port: 9443 ssl: bundle: managementbundle: key-store-type: PKCS12 key-store: classpath:certificate.p12 key-store-password: your_password key-alias: yourdomain key-password: your_password ocsp: enabled: true spring: ssl: bundle: pemfile: certificate: classpath:cert.pem private-key: classpath:key.pem ocsp: enabled: true application: name: ssl-bundle-demo将
ocsp.enabled设置为true即可启用 OCSP Stapling。 这需要在mybundle,managementbundle, 和pemfile三个bundle中分别进行配置。 -
确认 OCSP Stapling 是否生效:
可以使用
openssl s_client命令连接到服务器,并检查 OCSP Stapling 是否生效。openssl s_client -connect localhost:8443 -status如果 OCSP Stapling 生效,你应该在输出中看到
OCSP response: ...这样的信息。如果没有生效,检查服务器日志,查看是否有 OCSP 相关的错误信息。通常是因为 CA 服务器不可达,或者证书配置不正确。
5. TLS 1.3 会话恢复配置
TLS 1.3 引入了更高效的会话恢复机制,可以减少 SSL/TLS 握手的开销,提高性能。会话恢复允许客户端和服务器重用之前的会话密钥,而无需完全重新协商。
-
启用 TLS 1.3:
在 Spring Boot 中,默认情况下会启用 TLS 1.3(如果 JDK 支持)。 但是,为了确保启用,你可以显式地配置支持的 TLS 协议版本。
在
application.yml中配置支持的 TLS 协议:server: port: 8443 ssl: bundle: mybundle: key-store-type: PKCS12 key-store: classpath:certificate.p12 key-store-password: your_password key-alias: yourdomain key-password: your_password enabled-protocols: TLSv1.3 management: server: port: 9443 ssl: bundle: managementbundle: key-store-type: PKCS12 key-store: classpath:certificate.p12 key-store-password: your_password key-alias: yourdomain key-password: your_password enabled-protocols: TLSv1.3 spring: ssl: bundle: pemfile: certificate: classpath:cert.pem private-key: classpath:key.pem enabled-protocols: TLSv1.3 application: name: ssl-bundle-demo设置
enabled-protocols为TLSv1.3。 你也可以同时支持多个协议版本,例如enabled-protocols: TLSv1.2,TLSv1.3。 -
配置会话缓存:
为了有效利用会话恢复,你需要配置会话缓存的大小和超时时间。 这可以通过 Tomcat Connector 的属性进行配置。
在
TomcatConfiguration中配置:import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatConfiguration { @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainerCustomizer() { return tomcatServletWebServerFactory -> { tomcatServletWebServerFactory.addConnectorCustomizers(connector -> { connector.setScheme("https"); connector.setSecure(true); connector.setPort(8443); // HTTPS 端口 connector.setAttribute("SSLEnabled", true); connector.setAttribute("sslImplementationName", org.apache.tomcat.util.net.openssl.OpenSSLImplementation.class.getName()); connector.setAttribute("sslProtocol", "TLSv1.3"); // 显式指定TLS协议版本 connector.setAttribute("SSLCertificateFile", "classpath:cert.pem"); // PEM 格式证书路径 connector.setAttribute("SSLCertificateKeyFile", "classpath:key.pem"); // PEM 格式私钥路径 connector.setAttribute("sessionCacheSize", "1000"); // 会话缓存大小 connector.setAttribute("sessionTimeout", "300"); // 会话超时时间 (秒) }); }; } }sessionCacheSize设置会话缓存的大小(例如 1000 个会话),sessionTimeout设置会话超时时间(例如 300 秒)。 -
验证会话恢复是否生效:
可以使用
openssl s_client命令连接到服务器,并在第一次连接后关闭连接,然后再次连接。 如果会话恢复生效,第二次连接的速度应该比第一次快。openssl s_client -connect localhost:8443 -tls1_3在输出中,你可以观察到会话是否被重用。 观察
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256这行输出。 如果是新的会话,会显示New。 如果是恢复的会话,可能显示Reused, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256或者类似的指示会话重用的信息。
6. 其他配置选项
SSL Bundles 还支持许多其他配置选项,例如:
trust-store和trust-store-password: 用于配置信任库,包含信任的 CA 证书。client-auth: 用于配置客户端身份验证,可以设置为need或want。ciphers: 用于配置支持的密码套件。
7. 代码示例:完整的 Spring Boot 应用
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
public class SslBundleDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SslBundleDemoApplication.class, args);
}
@RestController
static class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, SSL!";
}
}
@Configuration
public class TomcatConfiguration {
@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainerCustomizer() {
return tomcatServletWebServerFactory -> {
tomcatServletWebServerFactory.addConnectorCustomizers(connector -> {
connector.setScheme("https");
connector.setSecure(true);
connector.setPort(8443); // HTTPS 端口
connector.setAttribute("SSLEnabled", true);
connector.setAttribute("sslImplementationName", org.apache.tomcat.util.net.openssl.OpenSSLImplementation.class.getName());
connector.setAttribute("sslProtocol", "TLSv1.3"); // 显式指定TLS协议版本
connector.setAttribute("SSLCertificateFile", "classpath:cert.pem"); // PEM 格式证书路径
connector.setAttribute("SSLCertificateKeyFile", "classpath:key.pem"); // PEM 格式私钥路径
connector.setAttribute("sessionCacheSize", "1000"); // 会话缓存大小
connector.setAttribute("sessionTimeout", "300"); // 会话超时时间 (秒)
});
};
}
}
}
这个示例包含了一个简单的 Spring Boot 应用,它提供了一个 /hello 端点,并配置了 HTTPS、OCSP Stapling 和 TLS 1.3 会话恢复。 请确保 cert.pem 和 key.pem 文件位于 src/main/resources 目录下,并且 application.yml 文件也配置正确。
8. 故障排除
- 证书问题: 确保证书有效,并且与密钥匹配。检查证书的有效期和域名是否正确。
- 密钥库密码错误: 确保在
application.yml中配置的密钥库密码正确。 - OCSP Stapling 失败: 检查 CA 服务器是否可达,以及证书是否支持 OCSP。查看服务器日志,查找 OCSP 相关的错误信息。
- TLS 版本问题: 确保 JDK 支持配置的 TLS 版本。 可以使用
java -version命令查看 JDK 版本。 - 防火墙问题: 确保防火墙没有阻止 HTTPS 流量。
9. 表格:SSL Bundle 配置选项
| 配置项 | 说明 |
|---|---|
key-store-type |
密钥库类型,例如 PKCS12, JKS。 |
key-store |
密钥库文件路径。 |
key-store-password |
密钥库密码。 |
key-alias |
密钥别名。 |
key-password |
密钥密码。 |
trust-store |
信任库文件路径。 |
trust-store-password |
信任库密码。 |
client-auth |
客户端身份验证,可选值为 need 或 want。 |
ciphers |
支持的密码套件列表。 |
enabled-protocols |
支持的 TLS 协议版本列表,例如 TLSv1.2,TLSv1.3。 |
ocsp.enabled |
是否启用 OCSP Stapling。 |
certificate |
PEM 格式的证书文件路径 (用于pemfile bundle)。 |
private-key |
PEM 格式的私钥文件路径 (用于pemfile bundle)。 |
文章总结:配置安全的应用
Spring Boot 3.2 的 SSL Bundles 提供了一种便捷的方式来配置 SSL/TLS,并支持 OCSP Stapling 和 TLS 1.3 会话恢复等高级特性。 通过正确配置这些特性,可以提高应用的安全性、性能和用户体验。请务必在生产环境中使用权威 CA 机构签发的证书。