http请求中没有set-cookie,却产生了jsessionid;tomcat产生两个sessionid,一个是自定义的sessionid(customSessionId),一个是默认的jsess

本文探讨了使用Spring Session和Redis实现场景下出现的双重SessionID问题:自定义的customSessionId与默认的jsessionid并存。文章深入分析了产生这一现象的原因,包括sourcemap文件的影响和404页面未明确禁用Session导致的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

项目使用了spring session,并用redis存储,以实现分布式环境下session同步;查看dev tools—>network时发现,有两个sessionid,一个是spring session中指定的customSessionId,一个是tomcat默认的jsessionid,
这里写图片描述

<!--spring-applicationcontext.xml中指定的customSessionId-->
<bean id="defaultCookieSerializer"
          class="org.springframework.session.web.http.DefaultCookieSerializer">
        <property name="cookieName" value="customSessionId" />
        <property name="cookiePath" value="/" />
</bean>

这里我就产生了疑问?明明指定了sessionId为什么还会有默认的jsessionid?既然spring统一管理了session就不会再有新session了呀?!并且在check network中请求后,却发现没有任何请求产生jsessionid,但是application中的的确确产生了jsessionid!

问题

截止到现在产生了两个问题,

  • http请求中没有set-cookie,却产生了jsessionid
  • tomcat产生两个sessionid,一个是自定义的sessionid(customSessionId),一个是默认的jsessionid;

探索

意想不到的source map

为了查清楚第一个问题,使用了排除大法,使用折半删除,最终定位到jquery-migrate-1.1.1.min.js这个文件,如果不引用此文件则没有jsessionid,为了排除js创建jsessionid的可能,搜索文件内容并未发现jsessionid或cookie的代码,这时想到chrome的请求与fiddler的请求不一样让fiddler抓包也许能看到不一样的东西,
这里写图片描述
果然不一样,凭空多了jquery-migrate.min.map请求且产生了jsessionid,几经搜索,得知这是source map,相当于min.js文件对应的源代码,chrome dev tools默认会下载此文件,至此我们明白了,因为是chrome浏览器本身发送的,所以在network中看不见而fiddler却能抓出来。
当然,我们可以关闭下载source map,

dev tools---->settings--->sources--->enable javascript source maps 去掉勾选

jsp中的session

我们注意到min.map请求响应代码是404,并且产生了jsessionid,没有办法只能跟踪java源代码,追踪到StandardHostValve,执行完invoke方法后,就会产生setCookie,可以排除filter产生jsessionId的可能,再看404.jsp,发现没有指定session=“false”,所以会创建session,在invoke方法这一步等于执行了request.getSession(),因为这时的request已经是原始的request,未经spring包装的request肯定会产生原始的jsessionid,所以有两个sessionid,通过在404.jsp中指定session="false"就不会再从产生jsessionid;
这里写图片描述

原理

再回过头来说一下这个事情的原理,
spring session的原理是通过filter,暂且就叫它SpringSessionFilter吧,document要求它必须放在最前边,这样就能保证它会比其他filter先执行,它将tomcat的request、reponse,封装为spring的request、response,从而后边的filter/controller…获取到的request、response都是spring的request、response,这样在controller中request.getSession()肯定是spring制定的springSessionId。

public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
            throws IOException, ServletException;

但是StandardHostValve在springsessionfilter的前边执行(看上图的线程栈),所以它获取到的request、response仍然是原始的,所以此时request.getSession()获取到的就是原始的jsessionid。

引出来的段子

由于无法debug tomcat源码,所以standardhostvalve具体功能无从推断,这个还引出tomcat打源代码包的段子

后记

通过这个问题,在跟踪源码阶段,基本了解了spring session原理以及shiro的session原理,filter、filter chain、proxiedfilterchain,跟源码受益无穷呀。

参考

JavaScript Source Map 详解
集成Shiro后当遇到404错误时会丢失session

个人公众号

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值