java - 控制 session 时间戳是否更新

标签 java spring tomcat

在我的应用程序中,它在 Tomcat 7.0 上使用 Spring Web MVC 运行,我有一些 Controller ,尽管对它们的请求需要身份验证和有效 session ,但我不希望更新 session 的到期时间戳。换句话说,我希望 session 恰好在没有发生此特定 HTTP 请求的时候过期。

如果重要的话,这些都是 AJAX 方法,尽管我不知道它是否重要。

这可以通过通用 Java EE 或一些特殊的 Tomcat Hook 来完成吗?还有另一种方法可以实现这一目标吗?我知道 http://download.oracle.com/javaee/6/api/javax/servlet/http/HttpSession.html#setMaxInactiveInterval%28int%29但这似乎与我想要的几乎相反。

最佳答案

没有。 在 Spring 和您的应用程序有机会处理来自当前用户浏览器的 HTTP 请求之前,当前用户的 session 已根据 Servlet 规范由 tomcat 更新。因此 Spring 和您的应用程序无法控制更新当前用户的 session 。

servlet-3_1-final.pdf 的“7.6 最后访问时间”说“The 当作为 session 一部分的请求首先由 Servlet 容器处理时, session 被认为已被访问。”

如果 Tomcat 是 Servlet 容器。

Request.getSession()getSession(boolean create) 被调用时: 看 Line 2955 of Request.javaLine 269 of Session.java

据说

“/**
* 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.
*/“  

相关实现类Line 675 of StandardSession.java 一旦 Request.getSession()getSession(boolean create) 被调用,现有 session 将通过更新 thisAccessedTime

来更新

分享了一个调试过程,以查看现有 session 在哪里更新

  • Tomcat 9.0.38(未集群部署)
  • Spring 框架版本 4.3.12.RELEASE
  • Spring-security 版本 4.2.4.RELEASE
  • Servlet 3.1

操作:

  1. 登录应用程序,现在当前用户的 session 已经存在。
  2. Line 686 of StandardSession.java 上启用断点
  3. 点击任何 UI 按钮触发 HTTP 请求。

参见 Line 511 of org.apache.catalina.authenticator.AuthenticatorBase 引用https://imgur.com/a/QJ3IJxh它显示逻辑为

  • 通过请求 header “Cookie:”中的 session ID 查找 session JSESSIONID'
  • 通过计算 timeNow - thisAccessedTime 来检查 session 是否仍然有效
  • 如果当前用户 session 仍然有效,则使用访问时间更新 thisAccessedTime。 这是第一个也是唯一一个session更新的地方

之后这个方法下面的调用就不会调用access()了,这个可以看的时候

继续HTTP请求处理进度,在Line 541 of org.apache.catalina.authenticator.AuthenticatorBase过滤链处理 Line 110 of org.springframework.security.web.context.HttpSessionSecurityContextRepository.javaLine 130 of org.springframework.security.web.session.ConcurrentSessionFilter.javahttps://imgur.com/a/MfjJ2ey

只有Tomcat可以控制更新thisAccessedTime来更新现有 session 的有效时间。

决议

其实目的是为了达到一种效果,貌似一些特殊的HTTP请求(一些特殊的API,URL)不能更新在线用户的session,所以如果只剩下这些API调用,就没有了其他正常的 API 调用出现在一段时间的有效 session 间隔内,然后使 session 无效。

在选择以下选项之前,需要根据您的场景进行权衡

A>找一个切点,options可以

  1. javax.servlet.Fitler 的自定义实现 Servlet上下文过滤链结束
  2. 的定制实现 org.springframework.web.filter.GenericFilterBean 在最后 Sprint 内部过滤器链的过滤器链。
  3. 的定制实现 org.springframework.web.servlet.HandlerInterceptor

然后

  • 对于普通的 API 调用:记录一个自定义的 session 属性 thisAccessedTime
  • 对于特殊的 API 调用:使用 session 属性 thisAccessedTime 检查 session 是否仍然有效。如果它已过期则使 session 无效

B> javax.servlet.Fitler 的自定义过滤器实现,位于 Servlet 上下文过滤器链的末尾 使用完全自定义的 session 生命周期和 session 事件实现包装 Request.getSession()getSession(boolean create)

C> 用于实时通信的 Websocket 和 Long Polling

关于java - 控制 session 时间戳是否更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19191668/

相关文章:

java - 如果 1+ 个实例具有相同(最小)值,如何从确定最小值的循环中随机选择一个对象?

java - 使用非 Spring Groovy 类中的服务

java - 无需指定端口 8080 即可运行 Tomcat

tomcat - Eden空间在哪里设置?

java - 如何从 WSDL 生成/创建服务端点?

流过滤器中的 Java 反射

java - Selenium 不等待元素可点击

java - 将依赖项注入(inject)到不受 spring 管理的库类中

spring - broadleaf commerce 演示站点登录链接被重定向

java - 在 Jenkins 中部署 WAR 失败