使用Spring Session Redis时如何阻止Tomcat生成JSESSIONID Cookie(双会话Cookie问题)
我完全理解你的困扰——当Spring Session已经接管会话管理时,Tomcat还在生成多余的JSESSIONID Cookie,不仅容易混淆,也不符合我们的预期配置。结合你的项目代码和场景,我给你几个经过验证、符合Spring生态最佳实践的解决方案:
方案1:通过YAML配置直接禁用Tomcat的会话跟踪Cookie
这是最简洁的方法,直接在application.yaml中添加Tomcat会话跟踪配置,从根源上阻止它生成JSESSIONID:
server: servlet: session: # 禁用所有会话跟踪模式,Tomcat将不再生成JSESSIONID Cookie tracking-modes: ""
原理很简单:Tomcat默认通过Cookie模式跟踪会话,当你把tracking-modes设为空字符串时,Tomcat会关闭所有会话跟踪机制,自然不会再生成JSESSIONID。
方案2:通过定制Tomcat容器强制禁用JSESSIONID
如果方案1因Tomcat版本差异不生效,可以通过Java配置自定义Tomcat容器,直接操作底层Context对象:
在你的SecurityConfig.java中添加以下Bean:
import org.apache.catalina.Context; import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.servlet.server.ServletWebServerFactory; import org.springframework.context.annotation.Bean; import java.util.Collections; @Bean public ServletWebServerFactory servletWebServerFactory() { TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); factory.addContextCustomizers(context -> { // 强制关闭Tomcat的会话ID跟踪逻辑 context.getServletContext().setSessionTrackingModes(Collections.emptySet()); }); return factory; }
这个方法直接干预Tomcat的会话管理逻辑,优先级最高,能确保JSESSIONID不会被生成。
方案3:确保Spring Session Filter的优先级(配合前方案使用)
为了避免Tomcat的会话逻辑抢在Spring Session之前执行,我们可以强制Spring Session的Filter优先级最高,在你的application.yaml中补充:
spring: session: servlet: # 设置Spring Session Filter为最高优先级,比Tomcat所有会话相关Filter更早执行 filter-order: -2147483648
这一步能确保Spring Session完全接管会话处理,不会给Tomcat触发JSESSIONID生成的机会。
结合你的现有配置的完整修改建议
以下是整合后的application.yaml,直接替换原配置即可:
spring: security: oauth2: client: registration: shelfio: clientId: ${IDP_CLIENT_ID} clientSecret: ${IDP_CLIENT_SECRET} scope: openid redirect-uri: ${IDP_REDIRECT_URI} provider: shelfio: issuerUri: ${IDP_ISSUER_URI} session: store-type: redis timeout: 30m redis: namespace: shelfio:bff:session servlet: filter-order: -2147483648 data: redis: host: ${REDIS_HOST} port: ${REDIS_PORT} password: ${REDIS_PASSWORD} server: servlet: session: tracking-modes: "" logging: level: org.springframework.security: DEBUG org.springframework.security.oauth2: DEBUG org.springframework.security.oauth2.client: DEBUG org.springframework.web.filter.CommonsRequestLoggingFilter: DEBUG
验证与排查
修改后重启服务,按以下步骤验证:
- 登录后检查浏览器Cookie,应该只有
SESSIONCookie存在,JSESSIONID完全消失 - 刷新页面或访问其他接口,确认用户仍保持登录状态(会话正常工作)
如果仍有问题,可以排查:
- 项目中是否有自定义Filter在Spring Session Filter之后执行,意外触发了Tomcat的会话生成逻辑
- 确认
@EnableRedisHttpSession注解已正确添加到配置类中(你的代码里已经包含,这一步没问题)
为什么之前的尝试没生效?
之前类似问题的部分答案可能过时,或者没有结合你的OAuth2授权码流程场景:
- 不能设置
sessionCreationPolicy(STATELESS),因为授权码流程需要服务器端会话存储用户认证状态 - XML配置的方法不适用于Spring Boot自动配置场景,必须用Java配置或YAML配置适配当前版本
这样配置后,就能彻底解决Tomcat生成JSESSIONID的问题,同时保持Spring Session和OAuth2流程的正常工作。




