SpringBoot 2.7中如何销毁HTTPS通信完成后的TLS会话密钥
问题描述
我基于SpringBoot 2.7开发了一个简单的Rest API控制器,代码如下:
@RequestMapping("/v1") @RestController public class AgentController { @PostMapping("/api/list") public ResponseEntity<ApiResponse> getList(@RequestBody ApiRequest requestBody, HttpServletRequest request) { // some codes return response; } }
想要销毁TLS通信中使用的加密密钥,但不知道怎么访问它,不确定能不能在getList()方法里实现,还是要借助其他SpringBoot类。尝试了以下代码,但session变量始终是null:
HttpSession session = request.getSession(false); System.out.println("1"); if (session != null) { System.out.println("2"); SSLSession sslSession = (SSLSession) session.getAttribute("javax.servlet.request.ssl_session"); // Some codes.. }
解决方法
先说说你之前的问题出在哪:javax.servlet.request.ssl_session是存在HttpServletRequest的属性里的,不是HttpSession的。而且你用request.getSession(false)时,如果当前请求没创建过HTTP会话,自然返回null,这和TLS会话根本不沾边。
1. 正确获取SSLSession
直接从HttpServletRequest里拿就行,不用绕HttpSession:
@PostMapping("/api/list") public ResponseEntity<ApiResponse> getList(@RequestBody ApiRequest requestBody, HttpServletRequest request) { // 直接从request属性中获取SSLSession SSLSession sslSession = (SSLSession) request.getAttribute("javax.servlet.request.ssl_session"); if (sslSession != null) { // 后续处理逻辑 } // some codes return response; }
2. 销毁TLS会话密钥的具体操作
TLS会话密钥的管理本来是Servlet容器(比如SpringBoot默认用的Tomcat)负责的,SSLSession接口本身没有直接销毁密钥的方法,但可以通过让SSLSession失效来触发密钥清理:
- 如果是Tomcat容器,可以强制让SSLSession失效:
if (sslSession != null && sslSession instanceof org.apache.tomcat.util.net.SSLSession) { // 调用Tomcat实现的invalidate方法销毁会话 ((org.apache.tomcat.util.net.SSLSession) sslSession).invalidate(); } - 说明:这么做只是让当前TLS会话失效,后续请求会重新建立新的TLS会话并生成新密钥。容器本身会在会话超时或闲置时自动清理密钥,手动销毁主要用于敏感场景下的即时清理需求。
3. 全局自动销毁方案(可选)
如果想让所有HTTPS请求完成后自动销毁TLS会话,可以写个Filter来处理:
@Component public class TlsSessionCleanupFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { try { // 先执行请求处理逻辑 chain.doFilter(request, response); } finally { // 请求完成后清理TLS会话 HttpServletRequest httpRequest = (HttpServletRequest) request; SSLSession sslSession = (SSLSession) httpRequest.getAttribute("javax.servlet.request.ssl_session"); if (sslSession != null && sslSession instanceof org.apache.tomcat.util.net.SSLSession) { ((org.apache.tomcat.util.net.SSLSession) sslSession).invalidate(); } } } }
把这个Filter注册到Spring容器后,所有请求处理完成后都会自动尝试销毁当前TLS会话。
内容的提问来源于stack exchange,提问作者ai-rin
相关产品推荐
相关产品推荐

