ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Sa-Token 临时 Token 认证实战指南:创建、解析、索引反查与 JWT 集成

Sa-Token 临时 Token 认证实战指南:创建、解析、索引反查与 JWT 集成 Sa-Token 临时 Token 认证实战指南创建、解析、索引反查与 JWT 集成【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token本篇技术指南围绕 Sa-Token 框架内置的「临时 Token」认证模块sa-token-temp展开系统讲解临时授权场景的适用条件、SaTempUtil工具类的创建/解析/删除 API、多业务线前缀隔离、基于 value 反查 token 的索引机制以及可选的 JWT 逻辑内核集成方案。读完本文你将能独立实现邀请链接、一次性接口防盗用、短时资源访问等需要分钟级时效授权的业务并能从源码层面理解其存储结构与过期机制。一、临时 Token 的适用场景短时授权与防伪在部分业务场景中我们需要一种临时授权的能力一个 token 的有效期并不需要像登录有效期那样长达七天、三十天而是仅仅需要五分钟、半小时。这类诉求与登录态完全不同Sa-Token 为此内置了独立的「临时 Token」模块类注释中将其定位为“有效期很短的一种 token一般用于一次性接口防盗用、短时间资源访问等业务场景”见 SaTempTemplate.java。一个非常典型的业务场景是超链接邀请机制你在一个游戏中创建一个公会(id10014)现在想邀请好友加入。若系统直接生成形如http://xxx.com/apply?id10014的链接攻击者只需把尾部参数改成10015就能偷偷加入别人的公会——明文参数完全无法防伪。正常商业项目的通行做法是对公会 id 做一层token 映射最终链接形如http://xxx.com/apply?tokenoEwQBnglXDoGraSJdGaLooPZnGrk。这一串随机字符取代了明文数据服务器收到请求后根据 token 反解出真正的公会 id10014。由于 token 完全随机攻击者无法推算出10015会对应怎样的 Token同时 token 有效期被刻意缩短五分钟、半小时进一步压缩了被滥用或泄露的窗口期。这套“随机映射 短有效期”的模型正是sa-token-temp模块的核心设计理念。需要注意该模块已内嵌到核心包sa-token-core无需引入任何额外依赖即可直接使用。二、创建、解析与删除核心 API 速览sa-token-temp对外提供统一的静态工具类SaTempUtil见 SaTempUtil.java所有方法内部委托给SaManager.getSaTempTemplate()返回的SaTempTemplate实例执行因此更换存储或逻辑内核时上层调用代码完全不变。最基础的四个操作如下// 根据 value 创建一个 token第二个参数为有效期单位秒 String token SaTempUtil.createToken(10014, 200); // 解析 token 获取 value并转换为指定类型 String value SaTempUtil.parseToken(token, String.class); // 获取指定 token 的剩余有效期单位秒 SaTempUtil.getTimeout(token); // 删除指定 token SaTempUtil.deleteToken(token);1. 有效期参数与取值约定timeout参数的单位为秒其取值约定在 SaTempUtil.java 的方法注释中有明确说明正整数token 的存活秒数到期后自动失效-1代表永久有效在getTimeout的返回值中-1代表永久有效-2代表 token 无效不存在或已过期见 SaTempUtil.java。2. 源码视角token 的生成与落库从 SaTempTemplate.java 的实现可以看出createToken的完整调用链为通过createTempTokenValue(value)生成随机 token 值——其随机串由UUID.randomUUID().toString().replace(-, )生成见randomTempToken方法生成过程会经SaStrategy.instance.generateUniqueToken去重校验避免碰撞调用saveToken将token - value的映射持久化到SaTokenDao存储 key 的拼装规则为tokenName : namespace : token见splicingTempTokenSaveKey方法其中默认命名空间为temp-tokenDEFAULT_NAMESPACE若指定了isRecordIndex true则额外记录 value 侧索引详见第四节。默认命名空间与存储 key 格式可以被单测直接印证SaTempTokenTest.java 中验证了satoken:temp-token: token 的存取路径并断言SaTempUtil.createToken(group-1014, 200)后dao.getObject(satoken:temp-token: token)可读回原值。3. 删除与失效的容错行为deleteToken对“不存在的 token”是无害操作源码在删除前先parseToken判空为空则直接返回不会抛异常见 SaTempTemplate.java。这一点同样有测试覆盖deleteToken_invalidToken_isNoOp用例断言对无效 token 调用删除不会抛出任何异常见 SaTempTemplateTest.java。三、多业务线前缀拼接与裁剪当多条业务线同时使用临时 Token 时为避免 value 相互混淆可以在 value 上拼接业务前缀加以区分// 如果由多条业务线都需要生成临时 token可以加个前缀进行区分 // 例如 shop_ 前缀代表商城业务线的资源标识 String token SaTempUtil.createToken(shop_1001, 1200);获取 value 时可以手动裁剪前缀也可以直接调用带cutPrefix参数的解析方法让框架自动完成裁剪与类型转换// 解析 token 获取 value并裁剪指定前缀然后转换为指定类型 SaTempUtil.parseToken(token, shop_, Long.class); // 返回 1001L前缀匹配失败时的行为如果指定了错误的前缀即使 token 本身是正确的上述方法也将返回null而不是报错。对应测试用例为parseToken_wrongPrefix_returnsNull用group-前缀去解析user-9001生成的 token返回结果为 null见 SaTempTemplateTest.java。从源码看裁剪逻辑位于 SaTempTemplate.java先解析原始 value若未指定前缀则直接按类型转换返回若指定了前缀则先校验前缀长度必须小于 32 位超过会抛出SaTokenException对应checkCutPrefixLength方法及其测试checkCutPrefixLength_rejectsLongPrefix再判断 value 是否以该前缀开头——以substring裁剪后转换类型否则返回 null。另外需要提醒parseToken(token, cutPrefix, cs)三参数方法的参数顺序在 v1.41.0 前后发生了变化。源码 Javadoc 明确指出旧版本 v1.41.0的三参数为service, token, class新版本为token, cutPrefix, class见 SaTempUtil.java升级时请注意此逻辑变化。四、根据 value 反查 token索引机制默认情况下框架只保存token - value的映射而不记录value - token的索引信息。这意味着拿到一个 value 无法反向查回它名下的所有 token。如果业务上需要反查例如同一用户/资源发放了多张邀请链接需要统一吊销则必须在创建 token 时把第三个参数设为true// 在创建 token 时指定第三个参数 true即可让框架在保存 token 时同时记录 token 索引信息 String token1 SaTempUtil.createToken(10004, 1200, true); String token2 SaTempUtil.createToken(10004, 1300, true); String token3 SaTempUtil.createToken(10004, -1, true); // 永久有效的 token 同样支持索引 // 获取 10004 对应的所有 token ListString list SaTempUtil.getTempTokenList(10004); System.out.println(list);1. 索引的底层存储结构开启索引后框架会在 value 对应的Raw Session中维护一张 token 索引表存储 key 为__HD_TEMP_TOKEN_MAP常量TEMP_TOKEN_MAP见 SaTempTemplate.java内部以Maptoken, 过期时间戳的形式记录每个 token 及其过期时间。SaTempTemplate构造时通过new SaRawSessionDelegator(namespace)绑定以temp-token为命名空间的 Session 读写委托见 SaTempTemplate.java。2. 索引的自动清理与 TTL 联动getTempTokenList(value)在返回结果前会先调用adjustIndex对索引做一次“整理”见 SaTempTemplate.java其核心逻辑是遍历索引表中的每个 token将过期时间戳换算为剩余 TTL剔除已失效的条目若整理后索引表仍有数据则写回 Session若已为空则直接删除整个索引 Session见adjustIndex方法及测试adjustIndex_allExpired_deletesSession后者验证索引全部过期后satoken:raw-session:temp-token:*会话被删除取所有存活 token 中最大的 TTL作为索引 Session 自身的过期时间保证 Session 与最晚到期的 token 生命周期一致。这一机制在测试 SaTempTokenTest.java 中有完整的闭环验证为 value1001依次创建 200s、300s、400s 的三个 token 后getTempTokenList(1001)返回 3 条记录且对应 Raw Session 的剩余存活时间在 395~401 秒之间即等于最长的 400s删除 token3 后列表变为 2 条Session TTL 相应收缩到约 300s再创建一个永久 token-1后Session TTL 变为-1永久。3. 删除 token 时的索引联动deleteToken在删除 token 本身之后也会同步清理索引若 value 对应的索引 Session 仍存在则从索引表中移除该 token 并重新调整 Session TTL见 SaTempTemplate.java确保索引与真实数据始终一致。五、集成 JWT以 JWT 作为逻辑内核提到“临时 Token 认证”很容易联想到专门干这件事的框架——JWT。sa-token-temp模块允许以 JWT 作为逻辑内核完成工作引入依赖后所有上层 API 保持不变底层由随机字符串 Redis 存储切换为 JWT 自包含签名令牌。1. 引入依赖Maven 方式dependency groupIdcn.dev33/groupId artifactIdsa-token-temp-jwt/artifactId version${sa.top.version}/version /dependencyGradle 方式implementation cn.dev33:sa-token-temp-jwt:${sa.top.version}从 pom.xml 可以看到该插件模块依赖sa-token-core与io.jsonwebtoken:jjwt并额外引入javax.xml.bind:jaxb-api以规避NoClassDefFoundError: javax/xml/bind/DatatypeConverterJDK 8 以上移除 JAXB 后必须的兼容处理。插件安装逻辑位于 SaTokenPluginForTempForJwt.java其install()方法将SaManager中的临时 Token 模板替换为SaTempTemplateForJwt实例。2. 配置 JWT 秘钥必填集成后必须在配置文件中指定 JWT 秘钥否则无法工作sa-token: # sa-token-temp-jwt 模块的秘钥 随便乱摁几个字母就行了 jwt-secret-key: JfdDSgfCmPsDfmsAaQwnXk秘钥的必填性在源码层面有强制校验SaTempTemplateForJwt.getJwtSecretKey()会读取配置若为空则抛出SaTokenException(请配置jwtSecretKey)见 SaTempTemplateForJwt.java。核心包默认实现的getJwtSecretKey()恒返回null见 SaTempTemplate.java单测jwtSecretKey_defaultsToNull亦对此进行了断言见 SaTempTokenTest.java。3. JWT 模式下的能力边界切换为 JWT 内核后API 的语义发生两处重要变化见 SaTempTemplateForJwt.javacreateToken不再生成随机串而是调用SaJwtUtil.createToken(value, timeout, jwtSecretKey)签发携带 value 与过期时间的签名令牌parseToken/getTimeout对应改为SaJwtUtil的验签解析无状态、无需查库受 JWT 无状态特性限制deleteToken与getTempTokenList两个方法会抛出ApiDisabledException错误码分别为 30302、30304提示 “jwt cannot delete token” / “jwt cannot get token list”——因为 JWT 一旦签发无法从服务端真正吊销也不存在服务端索引。因此选择哪种内核取决于业务诉求默认随机串方案支持主动删除与 value 反查索引适合需要吊销能力的内部业务JWT 方案免存储、可跨服务验签适合纯校验场景但需接受“签发后不可吊销”的约束。六、小结与最佳实践sa-token-temp模块以极小的 API 面覆盖了短时授权的主要诉求实践中的建议组合如下明文敏感数据一律不直接拼在链接里统一走SaTempUtil.createToken生成的随机映射时长控制在分钟级多业务线共存时在 value 上约定统一前缀解析时用parseToken(token, prefix, Class)自动裁剪注意前缀长度需小于 32 位需要统一吊销或盘点时创建时开启第三参索引借助getTempTokenList与deleteToken完成管理跨服务无状态验签场景引入sa-token-temp-jwt并配置jwt-secret-key同时接受其“不可删除、不可反查”的能力边界有效期语义统一遵守秒为单位-1永久getTimeout返回-2表示 token 已无效。以上 API 行为均可通过仓库内的单元测试 SaTempTokenTest.java 与 SaTempTemplateTest.java 直接复现验证可作为理解实现细节与排查问题的第一手资料。【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表