28 关于SpringSession的永不失效

2024-05-28 15:38
文章标签 失效 28 永不 springsession

本文主要是介绍28 关于SpringSession的永不失效,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前的时候, 有一个需求, 需要用户的 session 一直存在, 此session里面记录了一些 用户的一些业务数据, 需要 在关闭了浏览器之后, session中的数据, 依然 存在

环境 : SpringSession 来托管session, 采用 redis 来存储session, 以下代码基于 spring-session - 1.2.0.RELEASE

----- 手动分割线 -----

然后 对于这个问题, 我想的 就是直接 session.setMaxInactiveInterval(-1), 直接 让session永不过期不就解决了吗, 但是 同事按照这种思路 实现了一下, 结果 发现 还是关闭了浏览器之后, session 就"消失"了然后 上周的时候, ??, 周二吧, 好像是, 然后 跟了一下代码, 瞅了瞅, 看了一下 HttpSession.setMaxInactiveInterval, 以及我们这里的 委托给的 ExpiringSession. setMaxInactiveIntervalInSeconds 的注释, 上面也是很明晰的写了, "A negative time indicates that the session will never timeout.", 我特么 就在想 为什么没有生效呢??上周二的时候, 浏览器里面看 SESSION 对应的 expire/Max-Age 是 session, 因此 关闭了浏览器之后, sessionId 对应的 cookie 就失效了m, 然后导致了 session 的"消失", 然后 SpringSession 重新创建了一个 session, 这就造成了我们现在的情况

----- 手动分割线 -----

然后 本来就是想, 那天晚上空了的时候, 看一看, 谁知道 最近妈的, 都太忙了, 加班加班加班, 然后 只好留到了周末然后 昨天的时候, 又有一些朋友的其他的事情, 然后 只好留到了今天, 然后 今天下午的时候, 又重新溜了一下 SessionRepositoryFilter 的这部分的代码然后 忽略SpringSession管理session的部分的细节, 我们这里 直奔关于我们这里的这个问题的相关部分, 为什么 sessionId 对应的 cookie 的生命周期不为很长的一个时间, 而是默认的关闭浏览器就失效呢?定位到 SessionRepositoryRequestWrapper. commitSession, 这个方法, 这个方法调用的地方是, SessionRepositoryResponseWrapper. onResponseCommitted, SessionRepositoryFilter.doFilterInternal也就是在 Response 写出数据的时候, 以及SessionRepositoryFilter 以及之后的Filter 以及XXXServlet处理完了之后的时候 调用了一下 commitSessionSessionRepositoryFilter.doFilterInternal

	@Overrideprotected void doFilterInternal(HttpServletRequest request,HttpServletResponse response, FilterChain filterChain)throws ServletException, IOException {request.setAttribute(SESSION_REPOSITORY_ATTR, this.sessionRepository);SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response, this.servletContext);SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest, response);HttpServletRequest strategyRequest = this.httpSessionStrategy.wrapRequest(wrappedRequest, wrappedResponse);HttpServletResponse strategyResponse = this.httpSessionStrategy.wrapResponse(wrappedRequest, wrappedResponse);try {filterChain.doFilter(strategyRequest, strategyResponse);}finally {wrappedRequest.commitSession();}}




SpringSession 管理 session 的逻辑, 就在于 SpringSession 重写的几个 Wrapper, RequestWrapper, ResponseWrapper, SessionWrapper
这里 差不多就是创建了 Wrapper, 然后把逻辑留给之后的 Filter, 以及处理业务的Servlet, 然后 责任链回到了当前 Filter, 之后 commitSession


SessionRepositoryRequestWrapper. commitSession
		private void commitSession() {HttpSessionWrapper wrappedSession = getCurrentSession();if (wrappedSession == null) {if (isInvalidateClientSession()) {SessionRepositoryFilter.this.httpSessionStrategy.onInvalidateSession(this, this.response);}}else {S session = wrappedSession.getSession();SessionRepositoryFilter.this.sessionRepository.save(session);if (!isRequestedSessionIdValid()|| !session.getId().equals(getRequestedSessionId())) {SessionRepositoryFilter.this.httpSessionStrategy.onNewSession(session,this, this.response);}}}




这里 我们着重需要关注的是, 这里 SessionRepositoryFilter.this.httpSessionStrategy.onNewSession
this.sessionRepository.save(session) 这里, 持久化当前 session, 如果 Servlet 处理的过程中, 对于Session有一些处理, 这里外层统一处理一下, 持久化变更的数据[如果配置了 RedisHttpSessionConfiguration.flushMode为IMMEDIATE, 此配置会传到 RedisHttpSessionConfiguration. sessionRepository, 创建的 RedisOperationsSessionRepository, 然后这样, 创建的session, 每次有更新之后, 都会直接持久化到 redis中]
在客户端访问服务器第一次生成 session 的时候, 会处理一些业务, 放在这里onNewSession 


我们这里看看默认的 CookieHttpSessionStrategy 的实现
CookieHttpSessionStrategy. onNewSession
	public void onNewSession(Session session, HttpServletRequest request,HttpServletResponse response) {Set<String> sessionIdsWritten = getSessionIdsWritten(request);if (sessionIdsWritten.contains(session.getId())) {return;}sessionIdsWritten.add(session.getId());Map<String, String> sessionIds = getSessionIds(request);String sessionAlias = getCurrentSessionAlias(request);sessionIds.put(sessionAlias, session.getId());String cookieValue = createSessionCookieValue(sessionIds);this.cookieSerializer.writeCookieValue(new CookieValue(request, response, cookieValue));}


添加 sessionKey -> sessionId, 到sessionId的集合中, 然后 通过response写出到 cookie中, 然后 这里面就是 我们要关注的重点了, 也就是 为什么我们这里的 sessionId 对应的 cookie 关闭了浏览器就失效的原因了


DefaultCookieSerializer. writeCookieValue
	public void writeCookieValue(CookieValue cookieValue) {HttpServletRequest request = cookieValue.getRequest();HttpServletResponse response = cookieValue.getResponse();String requestedCookieValue = cookieValue.getCookieValue();String actualCookieValue = this.jvmRoute == null ? requestedCookieValue: requestedCookieValue + this.jvmRoute;Cookie sessionCookie = new Cookie(this.cookieName, actualCookieValue);sessionCookie.setSecure(isSecureCookie(request));sessionCookie.setPath(getCookiePath(request));String domainName = getDomainName(request);if (domainName != null) {sessionCookie.setDomain(domainName);}if (this.useHttpOnlyCookie) {sessionCookie.setHttpOnly(true);}if ("".equals(requestedCookieValue)) {sessionCookie.setMaxAge(0);}else {sessionCookie.setMaxAge(this.cookieMaxAge);}response.addCookie(sessionCookie);}


新建 cookie, 配置path, domain, 等等参数信息
配置 maxAge, 这里"sessionCookie.setMaxAge(this.cookieMaxAge);", 默认的 DefaultCookieStrategy. cookieMaxAge 为-1, 浏览器这边对应的就是关闭窗口 cookie 失效
然后 这里, 如果我们需要 自定义 cookie的声明周期的话, 需要 自己创建 CookieSerializer, 然后 配置下cookieMaxAge, 然后 吧刚才定义的 CookieSerializer 配置到 XXXHttpSessionConfiguration, 里面就可以了


完, 不过 溜了一圈, 里面 还是有一些疑惑的地方
spring - session- expirations : $timeoutTs [$timeoutTs + 300] [expires:$sessionId, ]- sessions- session : $sessionId [$timeoutTs + 300] { maxInactiveInterval : xx, lastAccessedTime : xx, creationTime : xx }- expires- $sessionId [$timeoutTs] { }


1. spring:session:sessions:expires 这一层的作用是什么??, 标记当前 有哪些存活的 session 吗 ?
2. spring:session:sessions:session:$sessionId 这一层为什么要让他多存活5分钟??, 
3. RedisOperationsSessionRepository. leanupExpiredSessions(), 这个定时任务存在的意义是什么?? 
留几个问题, 之后的时候, 再回来看看, 再来补充补充吧??




这篇关于28 关于SpringSession的永不失效的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1010986

相关文章

【vue3|第28期】 Vue3 + Vue Router:探索路由重定向的使用与作用

日期:2024年9月8日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉在这里插入代码片得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^ 1.01365 = 37.7834;0.99365 = 0.0255 1.02365 = 1377.4083;0.98365 = 0.0006 说

ider文件查找功能失效

在ider中,配置快速查找文件为ctrl+shift+R(Eclipse风格),有时明明类存在,却搜索不到,这时可以清除idea缓存并重启试试: 第一步:点击 File 选择 Invalidate Caches/Restart 第二步:

【抽代复习笔记】28-群(二十二):四道子群例题

例1:证明,循环群的子群是循环群。 证:设G = (a),H ≤ G。 (1)若H = {e},则H是一阶循环群; (2)设H至少包含2个元素,即设H = {...,a^(-k),a^(-j),a^(-i),a^0,a^i,a^j,a^k,...}, 其中a^i是H中正指数最小的元素,0<i<j<k, 下证a^i是H的生成元: 对任意的a^t∈H(t∈Z),存在q∈Z,使得t = qi

Form 表单的 resetFields() 失效原因

假设我们有如下代码:  <template><ElForm ref="formRef" :model="formModel" :rules="rules"><!-- 表单内容 --></ElForm></template><script setup>import { ref } from 'vue';const formRef = ref(null);const formModel = ref

【佳学基因检测】网站加密证书失效后,如何移除并为新的证书安装准备环境?

【佳学基因检测】网站加密证书失效后,如何移除并为新的证书安装准备环境? 当WoTrus DV Server CA证书失效后,你需要确保你的Nginx配置中不再引用该证书,并且移除或替换相关的证书文件。以下是具体步骤: 1. 确认Nginx配置文件 首先,检查Nginx的配置文件,确保它不再引用旧的WoTrus证书。如果你已经使用Certbot安装了Let’s Encrypt证书,Certbo

天天爱你的心永不变

爱一个人,能够爱多久,很多人都有这个疑问,很多人对于天长地久的爱情都存在怀疑。其实,就是你的怀疑让你的爱情在慢慢失去原来的味道,是你的怀疑将你的爱情逐渐推离你的生活。

wx.chooseMessageFile在pc端微信小程序失效解决方法

项目场景: 在uniapp上驱动微信开发者工具(下图) 在手机上和微信开发者工具中(图1)都可以上传成功, 打开pc端的微信小程序 在pc端打开小程序时点击上传没反应 问题描述 提示:这里描述项目中遇到的问题: 在pc端打开小程序上传的时候发现点击上传没有反应,通过(    console.log("打印====111")    )打印步骤发现wx.chooseM

【C++学习(28)】通俗一点讲解:std::bind 回调技术

std::bind 是 C++11 标准库中的一个功能,它允许你“绑定”某些参数到一个函数、成员函数或可调用对象上,从而生成一个新的可调用对象。这种新的可调用对象可以稍后被调用,而且其中一些参数已经被预先设置好了。这在回调函数和异步编程中特别有用。 下面我用一个通俗的例子来解释 std::bind 是如何工作的。 假设场景 假设你有一个家庭厨师,他有一个技能叫做“做饭”。做饭需要两个参数:一

sql 中使用like%、函数导致索引失效的解决方案

SELECTp1.*FROM cdr_voice_202407_0 AS p1 WHERELENGTH( p1.calling_number ) < 11 AND p1.calling_number LIKE '%10086%' 上边的sql中如果 calling_number  是索引  会导致索引失效 涉及的 WHERE 子句有两个条件: LENGTH(p1.calling_numbe

『功能项目』Unity连接读取本地数据库【28】

打开上一篇27账号登陆注册界面UI搭建的项目, 本章要做的事情是本地数据库的连接与读取数据库中的道具信息(刀、铁块) 访问官方网站:MySQL 一、下载Mysql 首页滑到最下面,选择Downloads下的MySQL Community server 点击查看下载历史版本 下载完毕后将文件解压到你想保存到的盘和目录内。我是将文件解压到E:Program FilesM