You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Spring Session Redis时如何阻止Tomcat生成JSESSIONID Cookie(双会话Cookie问题)

使用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

验证与排查

修改后重启服务,按以下步骤验证:

  1. 登录后检查浏览器Cookie,应该只有SESSION Cookie存在,JSESSIONID完全消失
  2. 刷新页面或访问其他接口,确认用户仍保持登录状态(会话正常工作)

如果仍有问题,可以排查:

  • 项目中是否有自定义Filter在Spring Session Filter之后执行,意外触发了Tomcat的会话生成逻辑
  • 确认@EnableRedisHttpSession注解已正确添加到配置类中(你的代码里已经包含,这一步没问题)

为什么之前的尝试没生效?

之前类似问题的部分答案可能过时,或者没有结合你的OAuth2授权码流程场景:

  • 不能设置sessionCreationPolicy(STATELESS),因为授权码流程需要服务器端会话存储用户认证状态
  • XML配置的方法不适用于Spring Boot自动配置场景,必须用Java配置或YAML配置适配当前版本

这样配置后,就能彻底解决Tomcat生成JSESSIONID的问题,同时保持Spring Session和OAuth2流程的正常工作。

火山引擎 最新活动