news 2026/9/13 22:42:01

Sa-Token 名词解释:Token、Session、loginId 与登录鉴权策略的系统梳理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Sa-Token 名词解释:Token、Session、loginId 与登录鉴权策略的系统梳理

Sa-Token 名词解释:Token、Session、loginId 与登录鉴权策略的系统梳理

【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架,让鉴权变得简单、优雅!—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token

在 Sa-Token 中,"Token""Session""登录策略"这些词经常被混用,而绝大多数会话逻辑 bug 的根源正是对这些基础概念的理解偏差。本文以官方文档《Sa-Token 名词解释》(sa-token-doc-new/docs/more/noun-intro.md) 为核心骨架,结合 StpUtil.java、SaTokenConfig.java 等源码逐一澄清五种 Token、两种过期时间、三种 Session、账号标识、登录/注销策略与三种鉴权方式,帮助你在阅读文档、排查问题和提出 issue 之前先建立准确的术语体系。

一、几种 Token:按产生来源区分五种令牌

Sa-Token 官方文档首先强调:Token 并非只有一种,按产生来源可分为五类,混用名称是最常见的理解偏差来源。

名称产生入口常见别名作用
token(会话 Token)StpUtil.login()satoken、会话Token维护用户登录状态
temp-token(临时 Token)SaTempUtil.createToken()临时Token一次性接口防盗用、短时间资源访问
Access-TokenOAuth2 模块访问令牌、资源令牌OAuth2 客户端访问授权资源的身份凭证
Refresh-TokenOAuth2 模块刷新令牌用于换取新的 Access-Token
Same-TokenSaSameUtil模块同源令牌子服务外网隔离场景下的内部调用鉴权

会话 Token(satoken)

即配置项tokenName默认值satoken所对应的令牌。从 StpUtil.java 可以看到,StpUtil.login(Object id)StpUtil.login(Object id, String deviceType)StpUtil.login(Object id, SaLoginParameter loginParameter)等重载统一委托给成员变量stpLogicStpLogic对象)完成登录并生成会话 Token;SaTokenConfig.java 中tokenName的注释也印证了它同时是"Cookie 名称、提交 token 时参数的名称、存储 token 时的 key 前缀"。

临时 Token

SaTempUtil.java 是独立的"临时 token 验证模块",其类注释写明用途:"有效期很短的一种 token,一般用于一次性接口防盗用、短时间资源访问等业务场景"。核心 API 为:

// 为指定 value 创建一个临时 token(timeout 单位:秒,-1 代表永久有效) String token = SaTempUtil.createToken(value, timeout); // 解析 Token 获取 value Object value = SaTempUtil.parseToken(token);

它与会话 Token 的关键区别在于:不产生登录态、不与loginId绑定,仅做"值 ↔ 令牌"的短期映射。

Access-Token 与 Refresh-Token

这两个令牌由 OAuth2 模块产生,其常量定义见 SaOAuth2Consts.java,配套的access_token/refresh_token校验逻辑分布在sa-token-plugin/sa-token-oauth2目录下(如 SaOAuth2DataResolver.java)。注意它与"会话 Token"的区别:OAuth2 的 Access-Token 授权主体是客户端(应用),而会话 Token 授权主体是登录用户

Same-Token

SaSameUtil.java 是"Samed-Token 同源系统身份认证模块",类注释说明其目标是"解决同源系统互相调用时的身份认证校验,例如微服务网关请求转发鉴权、微服务 RPC 调用鉴权"。常用 API:

// 获取 Same-Token(不存在则立即创建) String sameToken = SaSameUtil.getToken(); // 校验一个 Same-Token 是否有效(无效抛异常) SaSameUtil.checkToken(token);

其有效期由全局配置项sameTokenTimeout控制,默认 1 天,见 SaTokenConfig.java。

二、两种过期时间:timeout 与 active-timeout

文档把会话 Token 的过期机制归纳为两个独立参数:

  • timeout:会话 Token 的长久有效期,即 Token 最长能用多久;
  • active-timeout:会话 Token 的最低活跃频率,即 Token 必须隔多久至少访问一次系统,否则被冻结。

两者的官方配置形式(源自 token-timeout.md):

sa-token: # token 有效期(单位:秒),默认30天,-1代表永不过期 timeout: 2592000 # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 active-timeout: -1
# properties 风格 sa-token.timeout=2592000 sa-token.active-timeout=-1

源码侧这两个参数的定义与默认值见 SaTokenConfig.java:

/** token 有效期(单位:秒) 默认30天,-1 代表永久有效 */ private long timeout = 60 * 60 * 24 * 30; /** * token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结, * 默认-1 代表不限制,永不冻结(例如可以设置为 1800 代表 30 分钟内无操作就冻结) */ private long activeTimeout = -1;

官方文档用银行储蓄卡来类比:timeout相当于卡的最长使用年限,到期卡被删除(Token 过期必须重新登录);active-timeout相当于最低活跃要求,长期不动则被冻结(Token 被冻结但不会被删除)。两者可单独配置也可同时配置,只要有一个过期 Token 就不可用

与这两种过期时间直接相关的 API 都能在 StpUtil.java 中找到:

  • StpUtil.checkActiveTimeout():检查当前 Token 是否已被冻结,冻结则抛异常;
  • StpUtil.updateLastActiveToNow():手动续签,将"最后操作时间"更新为当前时间戳;
  • StpUtil.getTokenActiveTimeout()/StpUtil.getTokenTimeout():分别查询距离冻结还剩多久、Token 剩余有效时间(返回 -1 代表永久有效,-2 代表没有该值);
  • StpUtil.renewTimeout(long timeout):重置 token 的 timeout 有效期。

此外,配置项autoRenew(默认true)控制框架是否在每次直接或间接调用getLoginId()时自动进行过期检查与续签,可设为false将续签完全交给开发者手动控制。

三、三种 Session:账号维度、令牌维度、自定义维度

Sa-Token 文档将 Session 分为三种,区别在于"按什么主键分配":

Session 类型分配主键获取方式
Account-Session(账号 Session)账号 idStpUtil.getSession()
Token-Session(令牌 Session)每个 TokenStpUtil.getTokenSession()
Custom-Session(自定义 Session)任意指定的 SessionIdSaSessionCustomUtil.getSessionById(id)

Account-Session

框架只在调用StpUtil.login(id)登录时才产生 Session,且 Session 分配给账号 id而非客户端——PC 端和 APP 端登录同一账号得到的是同一个 Session,天然支持多端数据同步。操作示例:

// 获取当前会话的 Account-Session SaSession session = StpUtil.getSession(); // 从 Account-Session 中读取、写入数据 session.get("name"); session.set("name", "张三");

对应源码入口为 StpUtil.java 的getSession()getSessionByLoginId(Object loginId)等 Account-Session 相关方法区。

Token-Session

当需要"每个客户端独立"的数据(典型场景:某端两小时无操作自动下线)时,把数据放进共享的 Account-Session 会导致多端互相"续命"。Token-Session 就是按每个 Token 独立分配的:

// 获取当前会话的 Token-Session SaSession session = StpUtil.getTokenSession(); session.set("name", "张三");

不同设备即使登录同一账号,只要 token 不同,对应的 Token-Session 就不同。相关 API 见 StpUtil.java,包括getTokenSessionByToken(String tokenValue)与未登录也可使用的getAnonTokenSession()。另外配置项rightNowCreateTokenSession(默认false)决定 Token-Session 是登录时立即创建,还是首次调用getTokenSession()时惰性创建,见 SaTokenConfig.java。

Custom-Session

不依赖账号 id 或 token,以任意指定值作为 SessionId,可理解为通用的分布式缓存 Session:

// 获取指定 key 的 Custom-Session SaSession session = SaSessionCustomUtil.getSessionById("goods-10001"); session.set("name", "张三");

对应实现位于 SaSessionCustomUtil.java。Custom-Session 的会话有效期默认取全局配置的timeout,创建后可用session.updateTimeout(1000)单独修改。

三者的完整模型与结构图解见官方 Session模型详解:三个客户端登录同一账号(不共享 token)时,指向同一个 Account-Session,但各自持有不同的 Token-Session;简而言之——Account-Session 以账号 id 为主,Token-Session 以 token 为主,Custom-Session 以特定 key 为主。

四、账号标识:loginId、device、loginType

文档把"标识一个登录会话"拆成三个正交维度:

  • loginId:账号 id,用来区分不同账号,通过StpUtil.login(id)指定。从 StpUtil.java 的注释看,建议类型为long | int | String
  • device:登录设备类型,例如PCAPP,通过StpUtil.login(id, deviceType)指定;
  • loginType:账号类型(账号体系标识),用来区分同一系统中的User账号Admin账号

loginType 的机制在源码中非常直白:StpUtil是一个"空壳门面类",所有静态方法都转发给成员变量stpLogic,而其TYPE常量固定为"login"

public class StpUtil { /** 多账号体系下的类型标识 */ public static final String TYPE = "login"; /** 底层使用的 StpLogic 对象 */ public static StpLogic stpLogic = new StpLogic(TYPE); // 所有静态方法均为对 stpLogic 的转发 }

由此推出多账号体系的做法:新建一个StpUserUtil,把TYPE改为"user"即可得到一套与StpUtil完全隔离的登录/鉴权体系;也可以不复制类,直接声明new StpLogic("user")(Kit 模式)。完整方案(含注解鉴权的type属性、注解合并、同端多登录的 tokenName 隔离等)见 多账号认证文档。

注意 device 在 API 中实际以deviceType命名:SaLoginParameter.java 中字段名为deviceType,并额外提供deviceId(设备 id)供设备锁等场景使用;旧的setDevice()/getDevice()已标记@Deprecated,应改用setDeviceType()

五、几种登录策略:从文档概念到配置项

文档列出的七种登录策略,在 Sa-Token 中分别对应明确的配置项或独立模块。以下对照表以 SaTokenConfig.java 中的字段注释为依据:

文档中的策略含义对应实现/配置
单地登录(单端登录)同一时间只能在一处登录,新登录挤掉旧登录isConcurrent: false
多地登录(多端登录)不同地方可同时登录,新旧共存isConcurrent: true(默认)
同端互斥登录同类型设备单地点、不同类型设备可共存(参考 QQ 的登录模式)isConcurrent: true+ 登录时指定device,顶替范围由replacedRange控制
限量登录限制账号登录设备总数,超量后自动清退一个旧登录maxLoginCount(默认 12)+overflowLogoutMode
记住我模式设备重启后仍保持登录状态isLastingCookie: true(持久 Cookie)
单点登录进入多个系统只需登录一次SSO 模块(独立插件/文档体系)
同端多登录一个终端同时登录多个账号多账号体系 + 重写 tokenName 防覆盖

逐项说明:

  1. 单地/多地登录isConcurrent字段注释为"是否允许同一账号多地同时登录(为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)",默认trueisConcurrent=false时还可以用replacedLoginExitModeOLD_DEVICE旧设备下线 /NEW_DEVICE新设备登录失败)决定新旧设备谁放弃会话,用replacedRangeCURR_DEVICE_TYPE/ALL_DEVICE_TYPE)决定顶替范围。互斥登录的典型实践见 互斥登录文档。
  2. 限量登录maxLoginCount(同一账号最大登录数量,-1 不限)只在isConcurrent=true, isShare=false时生效;溢出时以何种方式清退旧会话由overflowLogoutMode决定(LOGOUT注销下线、KICKOUT踢人下线、REPLACED顶人下线)。
  3. 记住我isLastingCookie(默认true)决定 Cookie 是持久的还是临时的。StpUtil.login(id, isLastingCookie)还支持按单次登录动态指定。实现细节见 记住我模式文档。
  4. 单点登录:由独立 SSO 方案实现,概念与部署见 SSO 文档。
  5. 同端多登录:即"一个终端同时登录多个账号"。默认两套账号体系的 token 都写在名为satoken的载体里会互相覆盖,解决方式是重写stpLogic.splicingKeyTokenName()让不同体系使用不同 token 名称,详见 多账号认证文档 第 8 节。

登录参数的两种方式:全局配置 与 按次覆盖

以上所有登录行为都可以"按次登录"覆盖,这正是loginId/device之外的第三个重要类——SaLoginParameter.java。它的无参构造器会以全局SaTokenConfig为默认值初始化,未指定的项自动继承全局配置:

// 全局配置(yml) // sa-token: // is-concurrent: true // max-login-count: 12 // is-lasting-cookie: true // 按次覆盖:此次登录仅 PC 端、有效期七天、不共享 token StpUtil.login(10001, new SaLoginParameter() .setDeviceType("PC") .setTimeout(60 * 60 * 24 * 7) .setIsShare(false));

SaLoginParameter可覆盖的字段包括deviceTypedeviceIdtimeoutactiveTimeoutisConcurrentisSharemaxLoginCountisLastingCookiereplacedRangeoverflowLogoutModerightNowCreateTokenSession以及 Cookie 配置等,且每个字段均提供 setter 链式调用,便于登录接口中按业务动态组装登录行为。

六、几种注销策略

文档列出四种注销策略,其核心差异在"注销影响半径":

注销策略含义
单端注销只在调用登录的一端注销
全端注销一端注销,全端下线
同端注销发起注销后同类型设备端一起下线,不同设备类型不受影响
单点注销一个系统注销,所有系统一起下线(SSO 场景)

源码层面的基础抽象是枚举 SaLogoutRange.java:

public enum SaLogoutRange { /** token 范围:只注销提供的 token 指向的会话 */ TOKEN, /** 账号范围:注销 token 指向的 loginId 会话 */ ACCOUNT }

全局默认值由配置项logoutRange指定(默认TOKEN,即单端注销),见 SaTokenConfig.java。"同端注销"则通过在注销时传入deviceType参数实现——StpUtil.java 提供了按loginId + deviceType维度操作的logout(Object loginId, String deviceType)kickout(Object loginId, String deviceType)replaced(Object loginId, String deviceType)等重载,注释中均说明"填 null 代表覆盖该账号的所有设备类型"。

另外要注意"注销、踢人、顶人"三种下线方式的语义差异(均定义在 StpUtil.java):

  • logout:主动注销,对端再次访问提示未登录;
  • kickout:踢人下线,对端再次访问抛NotLoginException(场景值=-5);
  • replaced:顶人下线,对端再次访问抛NotLoginException(场景值=-4),用于"新登录挤掉旧登录"场景。

"单点注销"属于 SSO 体系的注销扩展,见 SSO 注销文档。

七、几种鉴权方式:代码、注解、路由拦截

文档把鉴权落地方式归纳为三种,源码中三者齐备:

1、代码鉴权

在代码里直接调用StpUtil.checkXxx相关 API,最灵活、可任意嵌套条件:

// 校验当前会话是否已登录,未登录抛 NotLoginException StpUtil.checkLogin(); // 校验当前账号是否拥有指定角色/权限 StpUtil.checkRole("admin"); StpUtil.checkPermission("article:add"); // 需要自定义逻辑时也可先 isXxx 判断再自行抛错 if(StpUtil.hasRole("vip")) { ... }

这些方法集中在 StpUtil.java 的"角色认证操作"与"权限认证操作"两个分区中。

2、注解鉴权

在方法或类上添加@SaCheckXxx注解。注解定义位于sa-token-coreannotation包下,如 SaCheckLogin.java、SaCheckRoleSaCheckPermissionSaCheckSafe等,每个注解配有独立的 handler(annotation/handler目录下的SaCheckLoginHandler等)。多账号体系下可通过注解的type属性指定校验哪套账号:

// 校验的是自定义 StpUserUtil 体系(type="user")的登录态 @SaCheckLogin(type = StpUserUtil.TYPE) @RequestMapping("info") public String info() { return "查询用户信息"; }

3、路由拦截鉴权

在全局过滤器或拦截器里通过SaRouter.match()拦截路由做集中鉴权,是"按 URL 白名单/黑名单"管控的常用形态:

// 在拦截器中:匹配一批路由,未登录一律拦截 SaRouter.match("/admin/**").check(r -> StpUtil.checkRole("admin")); // 混合多账号体系示例(来自多账号认证文档) SaRouter.match("/art/getInfo").check(r -> StpUtil.checkLogin()); SaRouter.match("/art/getInfo").check(r -> StpUserUtil.checkLogin());

路由匹配器实现见 SaRouter.java,它与SaFilter(Servlet 过滤器)及 Spring/Reactor/Solon 等平台的拦截器 starter 配合使用。

八、小结:一张表建立 Sa-Token 术语坐标系

概念族成员一句话区分
Tokentoken / temp-token / Access-Token / Refresh-Token / Same-Token按产生模块区分:登录模块、临时验证模块、OAuth2 模块、同源认证模块
过期时间timeout / active-timeout前者管"最长活多久",后者管"多久不活跃就冻结"
SessionAccount-Session / Token-Session / Custom-Session按账号 id / 按 token / 按自定义 key 分配
账号标识loginId / device / loginType哪个账号 / 哪种设备 / 哪套账号体系
登录策略单地、多地、同端互斥、限量、记住我、单点、同端多登录由 isConcurrent、replacedRange、maxLoginCount、isLastingCookie、SSO 模块、tokenName 隔离组合实现
注销策略单端 / 全端 / 同端 / 单点注销由 logoutRange 与 deviceType 维度控制,SSO 注销覆盖多系统
鉴权方式代码 / 注解 / 路由拦截checkXxxAPI、@SaCheckXxxSaRouter.match()

以上每个条目均可在当前仓库中定位到实现:登录与鉴权 API 见 StpUtil.java(核心逻辑在StpLogic),全局配置见 SaTokenConfig.java,按次登录参数见 SaLoginParameter.java。遇到"Token 过期""Session 不同步""新旧设备互踢"类问题时,建议先回到本表的坐标系确认自己讨论的到底是哪一种 Token、哪一层 Session、哪个维度的注销策略,再对照 登录认证文档 与 Token有效期详解 定位配置项,可避免绝大多数因概念混淆导致的误判。

【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架,让鉴权变得简单、优雅!—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 22:40:41

安全帽检测数据集处理全流程:从RAR解压到YOLO训练验证

简介:安全帽目标检测数据集压缩包面向计算机视觉初学者与工程开发者,聚焦工矿、建筑等高危作业场景下的人员与安全帽识别,可用于训练和评估目标检测模型。压缩包内共19688个文件,包含7571张jpg图像、6058个txt标注与6057个xml标注…

作者头像 李华
网站建设 2026/9/13 22:33:46

Easy-Vibe 安全思维指南:从攻防原理到上线前的安全检查清单

Easy-Vibe 安全思维指南:从攻防原理到上线前的安全检查清单 【免费下载链接】easy-vibe 💻 vibe coding 101|The first course for AI-native product builders. 项目地址: https://gitcode.com/GitHub_Trending/ea/easy-vibe 导读 本…

作者头像 李华
网站建设 2026/9/13 22:30:54

802.3协议解读 02:116章节 200 Gb/s 和 400 Gb/s 网络介绍 II

116.2 200 Gigabit 和 400 Gigabit 以太网子层总结116.2.1 协调子层(RS)和媒体无关接口(GMII)(1) RS(Reconciliation Sublayer,协调子层)(2) GMII…

作者头像 李华
网站建设 2026/9/13 22:29:04

高铁上的移动办公室:手机热点上架的连环验证

高铁上的移动办公室:手机热点上架的连环验证 一个高铁上还想上架的卖家自述: 「从北京回杭州的高铁上,我掏出笔记本想把手头三十个品传了。手机开热点,连上,登录,一切正常——好景不长,第三个品…

作者头像 李华