没有。在 Spring 和您的应用程序有机会处理来自当前用户浏览器的 HTTP 请求之前,tomcat 根据 Servlet 规范更新了当前用户的会话。因此 Spring 和您的应用程序无法控制更新当前用户的会话。
servlet-3_1-final.pdf 的“7.6 Last Accessed Times”说“当 Servlet 容器首先处理作为会话一部分的请求时,认为会话被访问。”
如果 Tomcat 是 Servlet 容器。
何时Request.getSession()
或被getSession(boolean create)
调用:参见
Request.java 的第 2955行
和
Session.java 的第 269 行
据说
“/**
* Update the accessed time information for this session. This method
* should be called by the context when a request comes in for a particular
* session, even if the application does not reference it.
*/“
StandardSession.java的相关实现类Line 675
一旦 Request.getSession()
或被getSession(boolean create)
调用,现有会话通过更新更新thisAccessedTime
共享调试过程以查看现有会话的更新位置
- Tomcat 9.0.38(未部署在集群中)
- Spring框架版本4.3.12.RELEASE
- Spring-security 版本 4.2.4.RELEASE
- 小服务程序 3.1
操作:
- 登录应用程序,所以现在当前用户的会话已经存在。
- 在StandardSession.java 的第 686 行启用断点
- 单击任何 UI 按钮以触发 HTTP 请求。
请参阅org.apache.catalina.authenticator.AuthenticatorBase 的第 511 行
参考https://imgur.com/a/QJ3IJxh它显示逻辑为
- 通过请求标头中的会话 ID 查找会话 'Cookie: JSESSIONID'
- 通过计算检查会话是否仍然有效
timeNow - thisAccessedTime
- 如果当前用户会话仍然有效,则更新
thisAccessedTime
访问时间。这是第一个也是唯一一个续期的地方
之后对该方法的以下调用将不会调用access(),这可以在何时看到
继续HTTP请求处理进度,在org.apache.catalina.authenticator.AuthenticatorBase的第541行过滤链处理
org.springframework.security.web.context.HttpSessionSecurityContextRepository.java的第110行和org.springframework.security.web的
第130行.session.ConcurrentSessionFilter.java
见https://imgur.com/a/MfjJ2ey
只有能够控制更新thisAccessedTime
的 Tomcat 才能更新现有会话的有效时间。
解析度
其实目的是为了达到一个效果,看起来像一些特殊的HTTP请求(一些特殊的API,URL)不能更新在线用户的会话,结果如果只剩下这些API调用,就没有其他正常的API了呼叫出现在有效会话间隔的一段时间内,然后使会话无效。
在选择以下选项之一之前需要根据您的场景进行权衡
A> 找到一个切点,选项可以
javax.servlet.Fitler
Servlet上下文过滤链末端的自定义实现
org.springframework.web.filter.GenericFilterBean
Sprint 内部过滤器链的过滤器链末端的自定义实现
。
- 一个定制的实现
org.springframework.web.servlet.HandlerInterceptor
然后
- 对于普通 API 调用:记录自定义会话属性
thisAccessedTime
- 对于特殊的 API 调用:使用 session 属性检查会话是否仍然有效
thisAccessedTime
。如果过期,则使会话无效
B>javax.servlet.Fitler
在 Servlet context Wraper 的过滤器链末端定制的过滤器实现,Request.getSession()
并getSession(boolean create)
具有完全定制的会话生命周期和会话事件实现。
C> Websocket 和 Long Polling 进行实时通信