5.0 KiB
Sa-Token 中的 Session会话 模型详解
1、Account-Session
提起Session,你脑海中最先浮现的可能就是 JSP 中的 HttpSession,它的工作原理可以大致总结为:
客户端每次与服务器第一次握手时,会被强制分配一个 [唯一id]
作为身份标识,注入到 Cookie 之中,
之后每次发起请求时,客户端都要将它提交到后台,服务器根据 [唯一id]
找到每个请求专属的Session对象,维持会话
这种机制简单粗暴,却有N多明显的缺点:
- 同一账号分别在PC、APP登录,会被识别为两个不相干的会话
- 一个设备难以同时登录两个账号
- 每次一个新的客户端访问服务器时,都会产生一个新的Session对象,即使这个客户端只访问了一次页面
- 在不支持Cookie的客户端下,这种机制会失效
Sa-Token Session可以理解为 HttpSession 的升级版:
- Sa-Token只在调用
StpUtil.login(id)
登录会话时才会产生Session,不会为每个陌生会话都产生Session,节省性能 - 在登录时产生的Session,是分配给账号id的,而不是分配给指定客户端的,也就是说在PC、APP上登录的同一账号所得到的Session也是同一个,所以两端可以非常轻松的同步数据
- Sa-Token支持Cookie、Header、body三个途径提交Token,而不是仅限于Cookie
- 由于不强依赖Cookie,所以只要将Token存储到不同的地方,便可以做到一个客户端同时登录多个账号
这种为账号id分配的Session,我们给它起一个合适的名字:Account-Session
,你可以通过如下方式操作它:
// 获取当前会话的 Account-Session
SaSession session = StpUtil.getSession();
// 从 Account-Session 中读取、写入数据
session.get("name");
session.set("name", "张三");
使用Account-Session
在不同端同步数据是非常方便的,因为只要 PC 和 APP 登录的账号id一致,它们对应的都是同一个Session,
举个应用场景:在PC端点赞的帖子列表,在APP端的点赞记录里也要同步显示出来
2、Token-Session
随着业务推进,我们还可能会遇到一些需要数据隔离的场景:
[!NOTE| label:业务场景] 指定客户端超过两小时无操作就自动下线,如果两小时内有操作,就再续期两小时,直到新的两小时无操作
那么这种请求访问记录应该存储在哪里呢?放在 Account-Session 里吗?
可别忘了,PC端和APP端可是共享的同一个 Account-Session ,如果把数据放在这里, 那就意味着,即使用户在PC端一直无操作,只要手机上用户还在不间断的操作,那PC端也不会过期!
解决这个问题的关键在于,虽然两个设备登录的是同一账号,但是两个它们得到的token是不一样的,
Sa-Token针对会话登录,不仅为账号id分配了Account-Session
,同时还为每个token分配了不同的Token-Session
不同的设备端,哪怕登录了同一账号,只要它们得到的token不一致,它们对应的 Token-Session
就不一致,这就为我们不同端的独立数据读写提供了支持:
// 获取当前会话的 Token-Session
SaSession session = StpUtil.getTokenSession();
// 从 Token-Session 中读取、写入数据
session.get("name");
session.set("name", "张三");
3、Custom-Session
除了以上两种Session,Sa-Token还提供了第三种Session,那就是:Custom-Session
,你可以将其理解为:自定义Session
Custom-Session不依赖特定的 账号id 或者 token,而是依赖于你提供的SessionId:
// 获取指定key的 Custom-Session
SaSession session = SaSessionCustomUtil.getSessionById("goods-10001");
// 从 Custom-Session 中读取、写入数据
session.get("name");
session.set("name", "张三");
只要两个自定义Session的Id一致,它们就是同一个Session
Custom-Session的会话有效期默认使用SaManager.getConfig().getTimeout()
, 如果需要修改会话有效期, 可以在创建之后, 使用对象方法修改
session.updateTimeout(1000); // 参数说明和全局有效期保持一致
4、Session模型结构图
三种Session创建时机:
Account-Session
: 指的是框架为每个 账号id 分配的 SessionToken-Session
: 指的是框架为每个 token 分配的 SessionCustom-Session
: 指的是以一个 特定的值 作为SessionId,来分配的 Session
假设三个客户端登录同一账号,且配置了不共享token,那么此时的Session模型是:
简而言之:
Account-Session
以账号 id 为主,只要 token 指向的账号 id 一致,那么对应的Session对象就一致Token-Session
以token为主,只要token不同,那么对应的Session对象就不同Custom-Session
以特定的key为主,不同key对应不同的Session对象,同样的key指向同一个Session对象