Sa-Token v1.46.0 发布 🚀,来看看有没有令你心动的功能!

Sa-Token 是一款 开源免费 的轻量级 Java 权限认证框架,主要解决:登录认证权限认证单点登录OAuth2.0微服务网关鉴权 等一系列权限相关问题。🔐

目前最新版本 v1.46.0 已推送至 Maven 中央仓库 🎉,大家可以通过如下方式引入:

xml 复制代码
<!-- Sa-Token 权限认证 -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot4-starter</artifactId>
    <version>1.46.0</version>
</dependency>

Spring Boot 3.x 请改用 sa-token-spring-boot3-starter,Spring Boot 2.x 请改用 sa-token-spring-boot-starter

该版本包含大量 ⛏️️️新增特性、⛏️底层重构、⛏️️️代码优化 等,下面容我列举几条比较重要的更新内容供大家参阅:

📦 更新点1:新增 sa-token-fory-json 插件,JSON 方案再添一位

这是官方规划里「JSON 模块集成 Apache Fory」的落地,把 Fory JSON 接到 SaJsonTemplate 上。

此前 Session / Redis 序列化主要是 Jackson(Boot 默认,JSON 里会写 @class)和 Fastjson2 / Snack(默认不写类型信息)。相对 Jackson:Fory 官方文档给出的吞吐更高,且默认不写类型信息,避开多态反序列化那条面;相对 Fastjson2:用法接近,适合已经在用 Apache Fory、或不想再绑 Fastjson 栈的项目。引入后 SPI 自动注入,不用自己包一层。

xml 复制代码
<!-- Sa-Token 整合 Apache Fory JSON -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-fory-json</artifactId>
    <version>1.46.0</version>
</dependency>

JSON 插件全家桶现在是:Jackson、Jackson3、Fastjson、Fastjson2、Fory JSON、Snack3、Snack4。Boot 2/3 默认仍是 Jackson,Boot 4 默认 Jackson3,用得顺不必为了换而换。

在线文档:JSON 序列化扩展 🔗

🌐 更新点2:新增 sa-token-rest-client / sa-token-rest-template 插件

SSO 模式三的 ticket 校验、单点注销、消息推送都要发 HTTP。此前只有 Forest、OkHttps 两套第三方客户端。Spring 项目本来就有 spring-web,再为 SSO 拉一套 HTTP 库,依赖和 API 都多一层。

本版按官方规划补上 Spring 官方客户端:sa-token-rest-templatesa-token-rest-client。相对 Forest / OkHttps:不引入第三方 HTTP 栈,跟 Spring 一条线。RestClient 相对 RestTemplate:它是 Spring Framework 6.1+ / Boot 3.2+ 的官方继任者,Boot 4 里 RestTemplate 已标记 deprecated,新项目优先 RestClient。Boot 2 或 Boot 3.0--3.1 没有 RestClient,继续用 RestTemplate 或 Forest。

xml 复制代码
<!-- Spring Boot 3.2+ / 4 优先 RestClient -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-rest-client</artifactId>
    <version>1.46.0</version>
</dependency>
运行环境 推荐插件
非 Spring / Solon sa-token-forestsa-token-okhttps
Spring Boot 2,或 Boot 3.0--3.1 sa-token-rest-templatesa-token-forest
Spring Boot 3.2+ / 4 优先 sa-token-rest-client

同一 classpath 只放一个 HTTP 插件。没配任何处理器会报错误码 30010。本版还加了 SSO Client 的 Spring Boot 4 示例。

在线文档:HTTP 请求扩展 🔗

🗄️ 更新点3:新增 sa-token-alone-redisson 插件,权限缓存和业务缓存拆开

来自 GitHub #710、Gitee #ICE2V0:alone-redis 要能配独立 Redisson。

升级有什么用: 现在 redisson 集成也可以做到权限缓存和业务缓存分离了,会话数据和业务 Redis 不再挤在同一个 Client 上,key 冲突、误删、codec 打架都能避开。Boot 4 另有 sa-token-alone-redis-by-spring-boot4

xml 复制代码
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-alone-redisson</artifactId>
    <version>1.46.0</version>
</dependency>

引入后不必再引 sa-token-redisson / sa-token-redisson-spring-boot-starter

yaml 复制代码
sa-token:
    alone-redisson:
        config: 
            singleServerConfig:
                address: "redis://127.0.0.1:6379"
                database: 2

configfile 二选一。示例覆盖单机、集群、Boot 3/4。

Boot 4 注意:Redisson 3.45 的 starter 仍引用已移除的 RedisAutoConfiguration不要引 redisson-spring-boot-starter,自己注册 Bean。SaTokenDaoForRedisson 默认 StringCodec,并可用 setAndKeepTTL 原子保留 TTL。fix: #791

在线文档:独立 Redisson 插件 🔗

🔧 更新点4:RedisTemplate 检索改 SCAN、update 保 TTL、key 可加前缀

这几条都是社区老工单:

  • searchData 用 KEYS 会堵 Redis:#702
  • update 后续期 TTL 偏移:#I80P5O#ICWJOQ
  • 多项目共用 Redis 要加前缀:#956

升级有什么用: 在线用户查询不再 KEYS *;改 Session 不会把过期时间抹成「再活一整段 timeout」;多系统共 Redis 可以 wrapKey 隔离开。

java 复制代码
public class MySaTokenDao extends SaTokenDaoForRedisTemplate {
    @Override
    public String wrapKey(String key) {
        return "my-app:" + key;
    }
}

KEEPTTL 需要 Redis >= 6.0。

🔔 更新点5:注销前侦听器,会话清掉之前还能读现场

来自 sa-token 小助手用户「潮汐」的建议:侦听器触发时设备信息往往已经没了,审计不好记。

升级有什么用: 踢人、顶人、主动注销前,还能读到 Token-Session、设备列表,写日志、发通知不用自己抢时序。

java 复制代码
@Override
public void doBeforeLogout(String loginType, Object loginId, String tokenValue, SaLogoutParameter logoutParameter) {
    SaSession session = SaManager.getStpLogic(loginType).getSessionByLoginId(loginId, false);
    SaTerminalInfo terminal = session == null ? null : session.getTerminal(tokenValue);
    // 记注销日志
}

对应钩子:doBeforeLogout / doBeforeKickout / doBeforeReplaced。不要用 StpUtil 读当前请求上下文,用参数里的 loginIdtokenValue 去查。

在线文档:全局侦听器 🔗

📋 更新点6:Session 新增 getList / getSet / getMap

本版主动补齐。以前从 Session 取集合,要么 get 完再强转,要么自己处理 Redis 回来的裸 List。现在把元素类型写在参数上,主要是为了让代码写得更优雅,调用更友善。

java 复制代码
// 以前
@SuppressWarnings("unchecked")
List<SysUser> users = (List<SysUser>) session.get("users");

// 现在
List<SysUser> users = session.getList("users", SysUser.class);
Set<String> roles = session.getSet("roles", String.class);
Map<String, Long> scoreMap = session.getMap("scoreMap", String.class, Long.class);

// 缺 key 时给默认集合
session.getList("users", SysUser.class, ArrayList::new);

OAuth2 索引、SSO Client 列表、ApiKey 索引也切到这套 API,业务侧同一套写法。

在线文档:Session 会话 🔗

🚪 更新点7:SSO 客户端支持按账号单点注销

社区提案:子系统删用户时,希望一行 API 通知认证中心把该账号全端打下线。

升级有什么用: 后台封号、离职回收,不必再自己拼 SSO 推送报文。

java 复制代码
// sso-server
SaSsoServerUtil.ssoLogout(loginId);

// sso-client(本地 loginId,框架按策略转成认证中心 id)
SaSsoClientUtil.ssoLogout(loginId);

在线文档:Sa-Token SSO 单点注销 🔗

🧩 更新点8:SaRequest / SaResponse / SaStorage 可策略创建

来自 GitHub #841:旧版靠继承 SaTokenContextForSpring 改上下文,v1.42 重构后那套父类没了。

升级有什么用: Nginx 改 URI、自定义 Request 包装,改策略函数即可,不用再继承已删除的上下文类。

SaStrategy 新增 createSaRequest / createSaResponse / createSaStoragegetSaTokenConfig 也可接管配置来源,方便从数据库读 Sa-Token 配置。

⚠️ 更新点9:两处不向下兼容,升级先看

1)allowLoginIdColon 默认 false。 官方一直强调 loginId 不要带冒号(持久化 key 用 : 分段)。本版源码直接拒登。存量项目如果 loginId 里真有冒号:

yaml 复制代码
sa-token:
    allow-login-id-colon: true

2)StpInterface.isDisabled 增加 loginType 参数。 自己实现了封禁查询的,要改方法签名。

另外:JWT extraData 禁止写入 loginTypeloginIddeviceTypeeffrnStr 等保留字段,撞名会直接抛错。

🛡️ 更新点10:修复 OAuth2 / SSO redirect 绕过 allow-url 漏洞

来自社区用户提交的漏洞报告:OAuth2 调用 /oauth2/doConfirm 时,redirect_uri 校验可被绕过;本版审查后确认 SSO 的 redirect 存在同类问题。

触发条件为(需同时满足):

  1. 项目搭了 SSO 认证中心OAuth2 授权服务器
  2. 请求里可以由前端(或攻击者)传入 redirect / redirect_uri
  3. allow-url 配了不安全通配(如 http://domain**出现在域名部分,前面不是/:)。

普通登录鉴权、没用 SSO/OAuth2 的项目,与这条无关。allow-url: "*" 等于主动放开白名单,也不在本条讨论范围。

会造成: ticket 或授权码被下发到第三方站点。

新版本: SSO 与 OAuth2 两侧同时拒绝 @%40%2540* 只能出现在最后一位,且前一位必须是 /:isUrl 支持 IPv6 方括号地址。生产环境请把 allow-url 配成明确地址。用了 SSO/OAuth2 的,建议升到 v1.46.0。

yaml 复制代码
sa-token:
    sso-server:
        clients:
            sso-client1:
                allow-url: http://sa-sso-client1.com:9003/*

感谢这位社区用户提交的漏洞报告。

🔐 更新点11:修复 Jackson 多态反序列化漏洞,新增类型白名单

这是本版对 JSON 反序列化路径的主动审查:使用 Jackson / Jackson3 把 SaSession 写入 Redis 时,JSON 里会带 @class 类型标记;旧版本未限制严格限制反序列化类型白名单,可能会在反序列化时触发 classpath 上的任意类。

触发条件为(需同时满足): 使用 SaJsonTemplate 去反序列化业务中未严格审查的 json 字符串。

fastjson / fastjson2 / fory-json / snack3 默认不写类型标记,一般不走这条面。不去使用 SaJsonTemplate 去反序列化业务中未严格审查的 json 字符串。本版起 sa-token-snack3 也不再写入类型信息。

会造成: 攻击者提交恶意 json 字符串,可能触发多态反序列化 RCE。

新版本: 增加 SaJsonStrategy 全局类型白名单,只允许白名单内类型参与这类反序列化。JDK 常见值类型、框架已实现 SaJsonType 的 Model 默认在名单里;你的业务实体默认不在。用了 Jackson 且 Session 里存了自定义对象的,升级后可能看到:

javascript 复制代码
无法反序列化的类型:com.pj.model.SysUser,请先将其注册到 JSON 全局类型白名单

推荐让实体实现 SaJsonType

java 复制代码
public class SysUser implements SaJsonType {
    // ...
}

也可以在 SpringApplication.run 之前 调用 SaJsonStrategy.instance.registerAllowType(SysUser.class),或在 META-INF/satoken/sa-json-type.list 按行写完整类名。JSON 插件初始化后再注册会失败。不要登记 Object.class。用了 Jackson + SaJsonTemplate 反序列化业务 json 字符串的,建议升到 v1.46.0,并先把业务类型登记进白名单。

在线文档:JSON 序列化扩展 🔗

📡 更新点12:修复 SSE / Flux 上下文未初始化,以及 Boot3 WebFlux setStatus

这两条都是社区报错工单:SSE 来自 Gitee #IC4XFE#ICB9OJsetStatus 来自 #IIAW1A、GitHub #916

SSE / Flux

在之前的版本中,SpringMVC 接口如果返回 SseEmitterFlux 等异步、流式结果,随后再调 StpUtil / SaHolder 会报:

makefile 复制代码
cn.dev33.satoken.exception.SaTokenContextException: SaTokenContext 上下文尚未初始化

这是因为 Context Filter 只注册了 REQUEST。流式返回会再走一遍 ASYNC dispatch,过滤器没挂上,ThreadLocal 上下文是空的。普通 @RequestMapping 一问一答不受影响。

新版本把 Filter 注册为 REQUEST + ASYNC,二次 dispatch 也会初始化上下文,一般不用再手改 Filter。

Boot3+ WebFlux / Gateway setStatus

在之前的版本中,Boot3+ 的 WebFlux 或 Gateway 里调用:

java 复制代码
SaHolder.getResponse().setStatus(401);

会报:

arduino 复制代码
java.lang.NoSuchMethodError: 'org.springframework.http.server.reactive.ServerHttpResponse setStatusCode(org.springframework.http.HttpStatus)'

这是因为 Boot2 的 ServerHttpResponse.setStatusCodeHttpStatus,Boot3 改成了 HttpStatusCode,旧 Reactor starter 字节码对不上。WebMVC 用户与这条无关。

新版本拆了 Boot2 / Boot3+ 的 Reactor 实现,Boot3+ 走 HttpStatusCode.valueOf(sc),不再报错。sa-token-dependencies 也不再锁死 Reactor 版本,避免跟 Spring Cloud Gateway 打架。fix: #622

📚 更新点13:文档站启用 .com 顶级域名,博客、多语言、安全策略

域名从 sa-token.cc 迁到 sa-token.com,请即使修改书签。独立博客上线;文档站暗色主题 5 种 IDE 风格;translate.js 多语言;README 有英/日/韩/俄/繁中。

随机数改用 SecureRandom。新增 SECURITY.md:安全问题走 GitHub Private Vulnerability Reporting 或邮件,不要开公开 Issue。

文档版本选择器改为动态加载。Solon 插件由 PathAnalyzer 换成 PathMatcher。

感谢 @Ran 补充 SECURITY.md(fix #932#877);感谢 @noear 适配 Solon PathMatcher(fix #IJTNJK)。

📜 完整更新日志

除了以上提到的几点以外,还有更多更新点无法逐一详细介绍,下面是 v1.46.0 版本的完整更新日志:

  • core:
    • 新增:侦听器新增注销前钩子 doBeforeLogout / doBeforeKickout / doBeforeReplaced重要
    • 新增:StpInterface.isDisabled 补充 loginType 参数。 不向下兼容
    • 新增:新增 allowLoginIdColon 配置,默认禁止 loginId 包含冒号。 不向下兼容
    • 修复:Jackson DefaultTyping 多态反序列化 RCE,新增 SaJsonStrategy 全局类型白名单。 重要 漏洞修复
    • 新增:getSaTokenConfig 策略支持自定义配置来源,方便从数据库中读取配置。
    • 新增:新增 SaRequest / SaResponse / SaStorage 创建策略。 fix: #841
    • 新增:Session 新增 getList / getSet / getMap 类型安全集合读取。
    • 修改:随机字符串/数字改用 CSPRNG(SecureRandom)生成。
    • 修复:isLastingCookie 为 null 时 getCookieTimeout 不再 NPE。
    • 修复:isUrl 支持 IPv6 方括号地址并拒绝裸 IPv6。
    • 修复:JSON 反序列化容错优化。 fix: #ICOTM8
  • 插件:
    • 新增:新增 sa-token-fory-json JSON 序列化插件。 重要
    • 新增:新增 HTTP 请求扩展插件 sa-token-rest-client / sa-token-rest-template重要
    • 新增:新增 sa-token-alone-redisson 独立连接插件及 Spring Boot 3/4 示例。 重要 fix: #710#ICE2V0
    • 新增:新增 sa-token-alone-redis-by-spring-boot4 插件及示例,实现 Spring Boot 4 下权限缓存与业务缓存分离。 重要
    • 新增:SaTokenDaoForRedisson 支持指定 Codec(默认 StringCodec),update 方法改用 setAndKeepTTL 原子保留原过期时间。 重要 fix: #791
    • 修复:sa-token-redis-template 及 jdk-serializer 在 update key 时 TTL 偏移的问题。 重要 fix: #I80P5O#ICWJOQ
    • 修复:redis-template searchData 由 KEYS 改为 SCAN。 重要 fix: #702
    • 新增:RedisTemplate Dao 支持重写 wrapKey 自定义键前缀。 fix: #956
    • 修复:sa-token-redis-template-jdk-serializer KEEPTTL 泛型编译错误。
    • 修复:Snack3 序列化不再写入类型信息,对齐 fastjson 安全策略。 漏洞修复
    • 修复:集成 JWT 时 extraData 禁止包含保留字段。 不向下兼容
    • 优化:升级 fastjson / fastjson2 至 2.0.64。
    • 优化:sa-token-dependencies 不再锁定 Reactor 版本,避免与 Spring Cloud Gateway 冲突。 fix: #622
  • starter:
    • 修复:Context Filter 注册 REQUEST+ASYNC,修复 SSE/Flux 流式返回上下文未初始化。 重要 fix: #IC4XFE#ICB9OJ
    • 修复:Boot3+ WebFlux/Gateway setStatus NoSuchMethodError。 fix: #IIAW1A#916#IHRIBY
    • 新增:新增 SSO Client Spring Boot 4 示例。
    • 新增:新增 sa-token-demo-first-run 首次运行引导示例。
    • 修复:demo-ssm 适配 v1.42.0+ 上下文机制。
  • Solon:
    • 优化:sa-token-solon-plugin 由 PathAnalyzer 适配改为 PathMatcher,优化 Config 示例。 merge: pr 364 fix: #IJTNJK
    • 优化:升级依赖 noear-redisx 至 1.8.5、noear-snack4 至 4.0.59。
  • SSO:
    • 修复:OAuth2/SSO redirect 参数绕过 allow-url 校验的安全漏洞。 重要 漏洞修复
    • 新增:SSO 客户端新增指定账号单点注销 API。
    • 补全:补全最新版 SSO NoSdk 模式实现,新增 SsoSignUtil
    • 修复:buildServerAuthUrl 识别 URL 编码后的 back 参数,back 为空时跳过追加,并增强重定向编码/解码健壮性。 fix: #842
    • 修复:getClient 统一通过 getClients 查找以支持子类覆盖。
    • 修复:NoSdk demo 签名校验补充时间窗与 nonce 防重放。 漏洞修复
    • 修复:订正 SSO-Client 接收消息推送地址的路由说明。
  • OAuth2:
    • 修复:redirect 参数绕过 allow-url 校验的安全漏洞。 重要 漏洞修复
    • 修改:expiresTime 为 -1 时按永久有效存储 Token。
    • 重构:doConfirm 确认授权流程统一校验。
    • 重构:SaOAuth2Dao 改用带 Class 参数的 getObject 反序列化。 fix: #IK5GYU
    • 修复:OAuth2 demo 拒绝授权时回传 state。
    • 新增:OAuth2 章节补充数据互通后的 token 过期策略说明。
  • 文档:
    • 修改:全仓库域名 sa-token.cc 统一迁移至 sa-token.com重要
    • 新增:上线独立博客系统,收录原创文章。 重要
    • 新增:文档站点多语言切换(基于 translate.js)。 重要
    • 新增:README 多语言版本(英文、日文、韩文、俄文、繁体中文)与切换入口。 重要
    • 新增:新增 SECURITY.md 安全策略及联系邮箱。 重要 merge: pr 933 fix: #932#877
    • 新增:文档站点暗色主题切换,支持 5 种 IDE 风格。
    • 新增:文档版本选择器改为动态加载(all-version-common.js)。 merge: pr 928 fix: #900
    • 新增:新增源码运行指南文档。
    • 新增:新增「Sa-Token 集成 Demos 示例大全下载」文档。
    • 新增:导航栏增加安全推荐与案例下拉菜单。
    • 优化:文档站点整体优化(侧边栏、首页、捐赠页、导航交互、API 手册等)。
    • 同步:同步公众号文章列表、博客列表、赞助者名单、企业登记案例。
    • 补充:补充 SSE/Flux 流式返回常见问题;补充按配置决定是否启用 Redis 的示例。 fix: #I9I4ZG
    • 修复:订正 API 手册、SSO/OAuth2/WebFlux/Dubbo 等文档错漏。
  • 其它:
    • 新增:新增乐之者java B站视频教程链接。 重要
    • 优化:统一日志文案用词,「帐号」改为「账号」。
    • 优化:统一 token 续期相关注释措辞。
    • 修复:修正 ConcurrentHashMap 的错误 import 路径。 merge: pr 359

更新日志在线文档直达链接:sa-token.com/doc.html#/m...

🌟 其它

代码仓库地址:gitee.com/dromara/sa-...

框架功能结构图:

相关推荐
tech_zjf1 小时前
当 AI 把 Next.js Route 越写越快:我为什么做了 next-route-kit
前端·后端
国产化创客1 小时前
ESP32-S3+INMP441+MAX98357 本地 WAV 录音播放方案详解
物联网·开源·音视频·智能家居·智能硬件
LayZhangStrive1 小时前
融360 一面
java·面试·后端开发
城管不管2 小时前
重生——第十次面试之开源中国一面挂
java·linux·开发语言·算法·面试·职场和发展·开源
Java小白笔记2 小时前
Windows系统免软件命令激活
java·网络·人工智能·windows·ai·ai编程
爱敲键盘的猴子2 小时前
深入理解 Java HashMap
java·hashmap
霸道流氓气质2 小时前
Java开发者AI编程常用MCP、Skills、Rules全景汇总
java·开发语言·ai编程
魔兽大山哥2 小时前
提示词注入很热闹:NL2SQL 里它打得穿 Prompt,打不穿执行层
后端
智能架构人生2 小时前
Java开发者技能如何迁移到Kotlin
后端