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

相关文章

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

oracle数据库索引失效的问题及解决

《oracle数据库索引失效的问题及解决》本文总结了在Oracle数据库中索引失效的一些常见场景,包括使用isnull、isnotnull、!=、、、函数处理、like前置%查询以及范围索引和等值索引... 目录oracle数据库索引失效问题场景环境索引失效情况及验证结论一结论二结论三结论四结论五总结ora

SpringBoot嵌套事务详解及失效解决方案

《SpringBoot嵌套事务详解及失效解决方案》在复杂的业务场景中,嵌套事务可以帮助我们更加精细地控制数据的一致性,然而,在SpringBoot中,如果嵌套事务的配置不当,可能会导致事务不生效的问题... 目录什么是嵌套事务?嵌套事务失效的原因核心问题:嵌套事务的解决方案方案一:将嵌套事务方法提取到独立类

MySQL的索引失效的原因实例及解决方案

《MySQL的索引失效的原因实例及解决方案》这篇文章主要讨论了MySQL索引失效的常见原因及其解决方案,它涵盖了数据类型不匹配、隐式转换、函数或表达式、范围查询、LIKE查询、OR条件、全表扫描、索引... 目录1. 数据类型不匹配2. 隐式转换3. 函数或表达式4. 范围查询之后的列5. like 查询6

【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

天天爱你的心永不变

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