
你说它跟 HttpSession 啥关系?能不能直接替换?一个账号多端登录,Session 数据到底共享还是隔离?
这些问题,我踩过坑之后才算真正搞明白。
今天这篇文章,咱们就把 Sa-Token 的 Session 机制彻底拆清楚。
这点真的很重要,我一开始也误解过。
Sa-Token 的 Session 是框架自己实现的 会话数据缓存组件,底层可以存内存、存 Redis,跟 Servlet 容器的 HttpSession 完全是两套东西。
也就是说:
// 获取当前登录用户的 Session
SaSession session = StpUtil.getSession();
// 存值
session.set("userName", "张三");
// 取值
String name = (String) session.get("userName");简单吧?但这里面有门道。
Sa-Token 提供了三种 Session 模型,我刚开始用的时候也是一头雾水。
后来在真实项目里踩了几次坑,才明白它们各自的定位。
绑定对象:账号 ID
这是最常用的。同一个账号,不管在手机登录还是电脑登录,共享同一个 Account-Session。
// 获取当前账号的 Account-Session
SaSession session = StpUtil.getSession();典型场景:
踩坑提醒:我曾经把「本次登录的设备信息」存在 Account-Session 里,结果用户换了个设备登录,数据全乱了。
绑定对象:Token
每个 Token 有独立的 Session,同一账号多端登录,各自隔离。
// 获取当前 Token 的 Token-Session
SaSession tokenSession = StpUtil.getTokenSession();典型场景:
这个设计我真的很喜欢。
之前做一个「强制指定设备下线」的功能,靠 Token-Session 轻松搞定,每个登录会话都有独立标识。
绑定对象:完全自定义
想用什么 ID 就用什么 ID,灵活度最高。
// 获取自定义 Session
SaSession customSession = SaManager.getSaTokenDao().getSession("cart_10001");典型场景:
模型 | 绑定维度 | 多端登录时 | 典型用途 |
|---|---|---|---|
Account-Session | 账号 ID | 共享 | 用户全局信息 |
Token-Session | Token 值 | 隔离 | 单次会话状态 |
Custom-Session | 自定义 ID | 按需 | 业务定制场景 |
这是我项目里的真实写法,供参考:
@RestController
public class LoginController {
@PostMapping("/login")
public String login(@RequestBody LoginDTO dto) {
// 1. 校验账号密码(省略)
UserInfo user = userService.checkLogin(dto);
// 2. 执行登录
StpUtil.login(user.getUserId());
// 3. 存储用户信息到 Account-Session
SaSession session = StpUtil.getSession();
session.set("userInfo", user);
// 4. 存储设备信息到 Token-Session
SaSession tokenSession = StpUtil.getTokenSession();
tokenSession.set("device", dto.getDeviceType());
tokenSession.set("loginIp", getRequestIp());
return "登录成功";
}
@GetMapping("/userInfo")
public UserInfo getUserInfo() {
SaSession session = StpUtil.getSession();
return (UserInfo) session.get("userInfo");
}
@PostMapping("/logout")
public String logout() {
StpUtil.logout();
return "登出成功";
}
}关键点:
Sa-Token 默认 Session 存在内存里,单机没问题。
但如果你是微服务架构,多实例部署,就得接 Redis 了。
<!-- Maven 依赖 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
<version>1.44.0</version>
</dependency># application.yml
sa-token:
token-name: satoken
timeout: 2592000
is-share: trueRedis 配好之后,Sa-Token 会自动把 Session 存到 Redis,多实例共享数据。
这块我当时折腾了半天,后来发现是 Redis 连接池没配好,跟框架本身没关系。
Sa-Token 的 Session 机制,设计得挺巧妙的:
选哪种,取决于你的业务场景。
别像我一样,一开始把啥都往 Account-Session 里塞,最后数据乱了才想起来有 Token-Session。
本章源码(GitHub)[1]
相关文章推荐:
[1] 本章源码(GitHub): https://github.com/BNTang/Sa-Token-Demo/tree/main/sa-token-demo-session
如果这篇文章帮到了你,不妨点个分享给同样需要的朋友吧! 你的每一次支持,都是我持续创作的动力!💪