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

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

<!-- Sa-Token 权限认证 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.40.0</version>
</dependency>

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

️ 更新点1:新增 Cookie 自定义属性支持

这是来自名为 “@massinger” 的用户创建的 GitHub issue #693

该开发者提出“是否可以为 Cookie 添加 Partitioned 属性,用于支持 iframe 嵌入跨域” 。

起初我以为 http 响应头 Cookie 参数只有 domainpathsecurehttpOnlysameSite 等几个扩展属性,

顺着这个 issue,我查阅了一下相关资料,这不查不知道,一查吓一跳 。

原来 Cookie 还有这么多我不知道的扩展属性:

(参考文章:https://blog.csdn.net/fengbin2005/article/details/136544226)

本着“可扩展性”的原则,本次版本更新没有补充这些属性的配置定义,而是直接增加了一个 extraAttrs 字段,你可以借助该字段扩展任意自定义属性。

举个例子,如下代码配置:

sa-token:
cookie:
domain: ""
path: /
secure: false
httpOnly: true
sameSite: Lax
extraAttrs:
Priority: Medium
Partitioned: ""
abc: def

将会促使 Sa-Token 框架生成以下格式的 Cookie 响应头️:

Set-Cookie: satoken=4d1a2052-29e0-4302-9ecd-ac54dece5fde; Max-Age=2592000; Expires=Tue, 4 Mar 2025 00:49:03 +0800; Path=/; HttpOnly; SameSite=Lax; Priority=Medium; Partitioned; abc=def

️ 更新点2:新增 SaFirewallStrategy 防火墙策略

危险 path 路径符校验是在最早 v1.37.0 就支持的功能,如果前端提交的请求 path 包含 “//、\、%2e、%2f、%5c、%25” 等特殊字符时,Sa-Token 全局过滤器将会截断请求,

返回类似 “非法请求:/test/login//” 的响应提示️。

因为包含这些特殊字符的请求通常被用于路径遍历、请求绕行等网络攻击行为⚔️。

本次更新重构了该功能的架构设计,抽离了一个统一的 SaFirewallStrategy “防火墙”组件,目前包含以下能力:

  • 请求 path 黑名单拦截。
  • 非法字符校验。
  • 白名单放行。

该组件在后续版本中还将计划增加ip校验、请求头校验等能力,并尝试引入 hooks 机制,以方便开发者更自由的进行功能扩展 。

更新点3:新增对分号字符的 path 路径校验,以预防潜在的网络攻击

此功能提案来源于 “船山信安” 公众号的一篇漏洞报告:Sa-Token对url过滤不全存在的风险点

该文章指出了 Sa-Token 对包含 “;” 字符过滤不全存在的风险点️:由于 Sa-Token 与底层 WebMVC 框架对 path 路径匹配的方式存在部分差异,

当前端提交的请求 path 中包含 “;” 字符,将可能导致请求绕过过滤器的权限检测,执行对应的 Controller 方法,从而导致越权问题。

目前在最新 v1.40.0 版本中已修复此问题,框架将从最顶层过滤器直接截断 path 中包含“;”字符的请求,避免鉴权被绕过的问题。

感谢“船山信安”团队做出的贡献。

更新点4:新增 OAuth2 Client 前端测试页,助你快速对接调试 OAuth2-Server

对于刚刚接触 OAuth2 概念的初学者来说,不仅 OAuth2 Server 端的搭建比较困难,其接入与测试也是一件极其繁琐的事情。

OAuth2 对接涉及大量繁琐的参数拼接、响应报文解析等步骤,仅一个授权码式的对接,其调试过程可能也要可能耗费数小时乃至数天。

为此,我们提供了一个专门对接 OAuth2 Server 的前端测试页️:

该测试页允许你:

  • 1️⃣ 在前端直接配置 OAuth2 Server 的主机地址、授权页地址、token接口地址、Scope参数 等信息。
  • 2️⃣ 一键拼接授权URL地址,一键测试对应平台 授权码式、隐藏式、密码式和客户端凭证式 的完整授权流程。
  • 3️⃣ 离线化自由部署,所有代码均在前端实现,敏感数据全程不经过第三方服务器,完整开源可自由二开。

通过该测试页面,你将非常直观的 get 到 OAuth2 四种模式的对接步骤、响应报文等信息,帮助你快速定位和解决 OAuth2 对接流程中的大部分问题 。

详情可参考该视频:Sa-Token v1.40 新功能预览:OAuth2 四种模式 一键测试页

更新点5:新增 UnionId 联合 ID 实现,方便跨应用识别用户

此提案来自于一位开发者对 官网 sa-token 小助手的咨询 :

这位开发者在使用 Sa-Token 的 OAuth2 模块时,需要一个叫做 UnionId 的功能。简单来讲:UnionId 可以帮助开发者在同主体的多个应用下定位到同一用户 。

作为立志要成为国内第一 java 权限认证框架的 Sa-Token 来讲,这是必须给安排上的。

详情可参考该视频️:OAuth2 授权流程中的 clientId、openId、unionId、userId 都是干嘛的?Sa-Token v1.40 预览:新增unionid支持

更新点6:新增 OAuth2-Server 端前后台分离示例与文档

有 Web Page 服务的地方就有前后台分离,当然 OAuth2 也不例外。

之前的版本 本质也是支持搭建 OAuth2-Server 端前后台分离服务的,但是由于官网仓库缺乏 Demo示例和相关介绍文档,导致 “OAuth2-Server 端能否前后台分离?” 成为点击量特别高的一个问题。

参考 issue:

本次 v1.40.0 版本针对 OAuth2-Server 端的前后台分离搭建补充了详细的 demo示例 与 说明文档。

在线官网直达地址:OAuth2-Server 端前后台分离

更新点7:新增 sa-token-freemarker 插件,整合 Freemarker 视图引擎。

来源 issue:#651

虽然前后台分离已成为当今的主流架构模式 ,但仍有一部分系统依旧采用前后台一体的方式进行搭建开发️。

在这部分应用中,80%的系统会采用 SpringBoot 官方推荐的 Thymeleaf 作为视图引擎组件。只有很少一部分才会采用 Freemarkerjspbeetl 等技术️。

但是!少~(三声转折),我们也要支持!

本次新增的 sa-token-freemarker 插件,用于整合 Freemarker 视图引擎。该插件使用方式非常简单,你只需要在 pom.xml 中引入如下依赖:

<!-- 在 Freemarker 页面中使用 Sa-Token 自定义标签 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-freemarker</artifactId>
<version>1.40.0</version>
</dependency>

然后便可以愉快的在 Freemarker Page 中,使用 Sa-Token 自定义标签控制某些内容是否显示,把权限精确到按钮级️:

<!-- 有user-add权限才显示按钮 -->
<@sa.hasPermission value="user-add">
<button class="btn-danger">点击发射核弹</button>
</@sa.hasPermission>

完整示例代码参考如下:

<div class="view-box" style="padding: 30px;">
<h2>Sa-Token 集成 Freemarker 标签方言 —— 测试页面</h2>
<p>当前是否登录:<#if stp.isLogin()>是<#else>否</#if></p>
<p>
<a href="login" target="_blank">登录</a>
<a href="logout" target="_blank">注销</a>
</p> <p>登录之后才能显示:<@sa.login>value</@sa.login></p>
<p>不登录才能显示:<@sa.notLogin>value</@sa.notLogin></p> <p>具有角色 admin 才能显示:<@sa.hasRole value="admin">value</@sa.hasRole></p>
<p>同时具备多个角色才能显示:<@sa.hasRoleAnd value="admin, ceo, cto">value</@sa.hasRoleAnd></p>
<p>只要具有其中一个角色就能显示:<@sa.hasRoleOr value="admin, ceo, cto">value</@sa.hasRoleOr></p>
<p>不具有角色 admin 才能显示:<@sa.notRole value="admin">value</@sa.notRole></p> <p>具有权限 user-add 才能显示:<@sa.hasPermission value="user-add">value</@sa.hasPermission></p>
<p>同时具备多个权限才能显示:<@sa.hasPermissionAnd value="user-add, user-delete, user-get">value</@sa.hasPermissionAnd></p>
<p>只要具有其中一个权限就能显示:<@sa.hasPermissionOr value="user-add, user-delete, user-get">value</@sa.hasPermissionOr></p>
<p>不具有权限 user-add 才能显示:<@sa.notPermission value="user-add">value</@sa.notPermission></p> <p>
从SaSession中取值:
<#if stp.isLogin()>
<span>${stp.getSession().get('name')}</span>
</#if>
</p> </div>

在线文档直达链接:Sa-Token 整合 Freemarker

更新点8:新增 sa-token-spring-el 插件,用于支持 SpEL 表达式注解鉴权。

fix issue:

“注解鉴权动态传递参数,支持‌SpEL表达式” 是呼声很高的一个提案,之前由于我本人对 SpringEL 表达式的了解非常有限,一直没有实现此功能。

在开发前,我构思了好几种实现方案,比如对 @SaCheckPermission("xxx") 注解支持动态表达式,或者手写一个简单的表达式解析引擎等。

最终权衡功能性、扩展性以及代码性能等 多个维度考虑⚖️,实现方案为新增一个独立的插件 sa-token-spring-el,该插件借助 SpringAOP 能力,提供一个 @SaCheckEL 鉴权注解,

用于书写 SpringEL 表达式进行鉴权✍️。

简单示例:

@RestController
@RequestMapping("/check-el/")
public class SaCheckELController { // 登录校验
@SaCheckEL("stp.checkLogin()")
@RequestMapping("test1")
public SaResult test1() {
return SaResult.ok();
} // 权限校验
@SaCheckEL("stp.checkPermission('user:edit')")
@RequestMapping("test3")
public SaResult test3() {
return SaResult.ok();
} // 参数长度校验
@SaCheckEL("NEED( #name.length() > 3 )")
@RequestMapping("test5")
public SaResult test5(@RequestParam(defaultValue = "") String name) {
return SaResult.ok().set("name", name);
} // SaSession 里取值校验
@SaCheckEL("NEED( stp.getSession().get('name') == 'zhangsan' )")
@RequestMapping("test8")
public SaResult test8() {
return SaResult.ok();
} }

在线文档直达链接:SpEL 表达式注解鉴权

值得一提的是:在本次更新中,@ly-chn 同学给了我很大的技术支持。是他提供的 demo 案例才让我顺利完成了 sa-token-spring-el 插件开发。

同时他也是 idea 插件 SpEL Assistant 的开发作者,该插件允许为自定义注解书写 SpEL 表达式时增加代码提示功能,

开源地址:https://github.com/ly-chn/SpEL-Assistant

更新点9:新增 MongoDB 集成示例,权限数据可以缓存到 MongoDB 中了!

merge pr:

集成 MongoDB 是我一直想做而没有做的一个功能,一来是因为我对 MongoDB 了解有限,二来我感觉 MongoDB 的数据存储格式也不如 Redis 更加合适。

有太多更加紧迫的提案需要我去实现,所以整合 MongoDB 一直处于搁置状态。

感谢来自 @lilihao 提供的 demo 示例,也算是补充了 Sa-Token 在这块的缺失。

在线文档直达链接:

更新点10:封禁模块新增支持实时从数据库查询数据

Sa-Token 默认将封禁信息储存在缓存中,缓存中的数据是 “临时性的”、“易丢失的”,而在大多数系统的设计中,需要将封禁数据持久化到数据库中。

要使封禁信息持久化,你只需要在调用 Sa-Token 的封禁 API 后,再继续调用插入数据库的代码即可

// 在 Sa-Token 框架中封禁指定账号
StpUtil.disable(10001, 86400); // 更改数据库中此人信息 (举例代码)
userMapper.disableUser(10001);

这样即可保证封禁数据同步插入到缓存和数据库中,但是还有一个问题,如果我们的程序或缓存中间件重启了,导致缓存数据丢失️, 那再调用 StpUtil.checkDisable(10001) 代码将没有效果,无法约束到此用户。

比较次的解决方案是在程序启动时,读取数据库中所有封禁信息同步到缓存中去,但是如果封禁记录较多这样将会严重拖慢程序启动时间⏱️。

v1.40.0 版本提供一种新的方案,你只需要实现 StpInterface 接口的 isDisabled 方法,即可让 Sa-Token 实时查询某个账号是否被封禁了指定业务。

@Component
public class StpInterfaceImpl implements StpInterface { /**
* 返回指定账号 id 是否被封禁
*
* @param loginId 账号id
* @param service 业务标识符
* @return 描述该账号是否封禁的包装信息对象
*/
public SaDisableWrapperInfo isDisabled(Object loginId, String service) {
// 查库操作 ... (此处仅做示例代码)
return SaDisableWrapperInfo.createDisabled(86400, 1);
} }

该方法返回值具有多种写法,分别代表不同的封禁策略,详细可参考在线文档:

Sa-Token 账号封禁

更新点11:文档新增内容

  • 文档首页新增:哔哩哔哩、抖音、微信视频号链接,欢迎大家关注️。
  • 导航栏视频新增 [fox说技术] 录制的 Sa-Token 课程链接 。
  • “API接口参数签名”章节 新增视频讲解链接(该课程由B站up主 [抓蛙师] 讲解录制)。
  • 文档首页首屏增加 “需求提交” 按钮,欢迎各位同学对 Sa-Token 后续版本提出你的需求与建议。
  • 文档首页以及 Readme 新增 gitcode G-Star badge 展示。
  • 文档新增新增团队成员展示。
  • 补全赞助者名单:v1.40 版本开发期间,共有20+用户进行打赏,总金额超过500元+,感谢这些用户的充电支持。

完整更新日志

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

  • core:

    • 新增:新增 Cookie 自定义属性支持。 fix: #693 [重要]
    • 新增:SaFirewallStrategy 防火墙策略:请求 path 黑名单校验、非法字符校验、白名单放行。 [重要]
    • 修复:新增对分号字符的 path 路径校验。 参考:Sa-Token对url过滤不全存在的风险点 [漏洞修复]
    • 修复: 修复部分场景下登录后已存在的 token-session 没有被续期的问题。 fix: #IA8U1O
    • 优化:优化 active-timeout 的检查与续期操作,同一请求内只会检查与续期一次。
    • 修复:SaFoxUtil.joinSharpParam 方法中不正确的注释。
    • 新增:封禁模块新增支持实时从数据库查询数据。
  • SSO:
    • 优化:SSO 示例代码的跨域处理由原生方式改为 Sa-Token 过滤器模式。
    • 新增:文档新增 “SSO整合 - NoSdk 模式与非 java 项目” 章节。
    • 新增:“不同 SSO Client 配置不同秘钥” 章节增加部分异常的处理方案提示,fix: #IAFZXL
    • 删除:sso demo 示例中部分不必要的代码内容。
  • OAuth2:
    • 新增:OAuth2 Client 前端测试页。 [重要]
    • 新增:UnionId 联合id 实现。 [重要]
    • 新增:oauth2-server 端前后台分离示例与文档。 fix: #I9DQGA#I9W2RU [重要]
    • 新增:OIDC 模式 nonce 随机数响应校验。 merge: pr311
    • 修复:错误方法名 deleteGrantScope(String state) -> deleteState(String state)
    • 修复:全局配置项 sa-token.oauth2-server.oidc.iss 无效的问题。
    • 新增:回收 Refresh-Token 方法: revokeRefreshTokenrevokeRefreshTokenByIndex
    • 新增:为 CodeModelAccessTokenModelRefreshTokenModelClientTokenModel 添加 createTime 字段,以记录该数据的创建时间。
    • 新增:为 Access-Token、Client-Token 添加 grantType 字段,以记录该数据的授权类型。
    • 新增:SaOAuth2Util.getCode 等方法,以更方便的获取、校验授权码。
  • 插件:
    • 新增:新增 sa-token-freemarker 插件,整合 Freemarker 视图引擎。 fix: #651 [重要]
    • 新增:新增 sa-token-spring-el 插件,用于支持 SpEL 表达式注解鉴权。 fix: #IB3GBB、fix: #IAIXSL、fix: #I9P24F [重要]
  • 文档:
    • 新增:新增 MongoDB 集成示例。 感谢 @lilihao 提供的示例。 merge: pr322pr667 [重要]
    • 新增:“fox说技术” 视频教程链接。
    • 新增:“API接口参数签名”章节 视频讲解链接(B站抓蛙师)。
    • 优化:文档首页首屏增加需求提交按钮。
    • 其它:补全赞助者名单、Dromara 项目链接等信息。
    • 新增:SpringBoot3.x 版本配置 Redis 注意事项。fix: #688
    • 新增:gitcode g-star badge 展示。
    • 修复:OAuth2 滞后的配置信息示例。
    • 新增:新增视频账号链接。
    • 新增:新增团队成员展示。

更新日志在线文档直达链接:https://sa-token.cc/doc.html#/more/update-log

其它

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

框架功能结构图:

本文章由 DeepSeek 参与指导与润色,感谢 DeepSeek 团队。

Sa-Token v1.40.0 发布 🚀,来看看有没有令你心动的功能!的更多相关文章

  1. RapidJSON v1.1.0 发布简介

    时隔 15.6 个月,终于发布了一个新版本 v1.1.0. 新版本除了包含了这些日子收集到的无数的小改进及 bug fixes,也有一些新功能.本文尝试从使用者的角度,简单介绍一下这些功能和沿由. P ...

  2. FineUIMvc v1.4.0 发布了(ASP.NET MVC控件库)!

    FineUIMvc v1.4.0 已经于 2017-06-30 发布,FineUIMvc 是基于 jQuery 的专业 ASP.NET MVC 控件库,是我们的新产品.由于和 FineUI(专业版)共 ...

  3. Jsonnet-PHP v1.3.0 发布,支持 PHP 7 使用 Jsonnet

    JsonNet-PHP 是 Google Jsonnet 对 PHP的支持扩展. pecl: http://pecl.php.net/package/jsonnet github: https://g ...

  4. Solon v1.11.0 发布,Hello Java

    一个更现代感的 Java 应用开发框架:更快.更小.更自由.没有 Spring,没有 Servlet,没有 JavaEE:独立的轻量生态.主框架仅 0.1 MB. @Controller public ...

  5. Yearning v1.3.0 发布,Web 端 SQL 审核平台

    企业级MYSQL web端 SQL审核平台. Website 官网 www.yearning.io Feature 功能 数据库字典自动生成 SQL查询 查询工单 导出 自动补全,智能提示 查询语句审 ...

  6. Solon Java Framework v1.12.0 发布

    一个更现代感的 Java 应用开发框架:更快.更小.更自由.没有 Spring,没有 Servlet,没有 JavaEE:独立的轻量生态.主框架仅 0.1 MB. @Controller public ...

  7. spring-boot-plus V1.4.0发布 集成用户角色权限部门管理

    RBAC用户角色权限 用户角色权限部门管理核心接口介绍 Shiro权限配置

  8. 微信快速开发框架(九)-- V3.0发布,代码已更新至Github 新增微店功能

    版本内容 1.修正了缺少对Event.View的支持 2.增加了用户UnionID 3.新增微信小店功能 4.多客服功能 5.单元测试 什么是UnionID 我们知道,每个用户针对一个微信公众账号都有 ...

  9. Kube-OVN 0.6.0 发布,支持 IPv6、流量镜像及更多功能

    Kube-OVN 是一个基于 OVN 的 Kubernetes 开源网络系统. 本次更新主要包含了以下内容: 1. 支持流量镜像 在安装 Kube-OVN 时可以开启 mirror 选项,会自动在每个 ...

  10. Gitea v1.17.0 正式发布 | 集成软件包管理器、容器镜像仓库

    我们自豪地宣布 Gitea v1.17.0 发布了.本次发布带来了诸多新特性和累积的更新,我们强烈建议用户在更新到最新版本之前仔细阅读发行注记. 在 1.17.0 版本的开发中我们一共合并了 645 ...

随机推荐

  1. Tensorflow 使用TPU训练

    要用TPU训练tensorflow模型,只能使用静态图.也就是要先通过keras的sequential或者函数式定义模型,而不能直接使用重写的Model类.例子如下,其中包含层的自定义,以及子像素卷积 ...

  2. http: server gave HTTP response to HTTPS client

    出现这问题的原因是:Docker自从1.3.X之后docker registry交互默认使用的是HTTPS,但是搭建私有镜像默认使用的是HTTP服务,所以与私有镜像交时出现以上错误. 这个报错是在本地 ...

  3. JVM最简生存指南

    本文由 ImportNew - Grey 翻译自 hadihariri.欢迎加入Java小组.转载请参见文章末尾的要求. 最近更新 : 2014年1月9日 为什么要写这个指南 持续更新 目标人群 基础 ...

  4. Ollma本地部署Qwen2.5 14B(不使用docker)

    部署机器硬件情况: 内存 :32GB 显卡 :3060 为什么不使用docker: 1.网上教程大多以docker为主 2.安装docker的时间太长,在等待的时候顺便尝试一下不用docker的部署 ...

  5. Tornado框架之基础(一)

    知识点 了解什么是Tornado框架 了解Tornado与Django的区别 Tornado的安装 了解Tornado的原理 掌握Tornado的基本写法 掌握Tornado的基本模块 tornado ...

  6. Vim之PHP语法检查

    在Linux下操作,一般都是使用vim进行文本编辑, 这个时候有可能不小心就会出现语法异常,导致程序错误 手动检查: 1) 编辑完成之后, 回到命令行下执行 php -l test.php 如果语法校 ...

  7. Ubuntu无法SSH登陆的解决方案

    1. 连接时出现提示 ssh_exchange_identification 问题提示: ssh_exchange_identification: read: Connection reset by ...

  8. 恭喜您获得【智能工具箱】,使用后图片大小-80%、视频大小-90%、PPT附带在线预览属性…

    小梁是一名小学英语老师,因为疫情影响,全市中小学都要求师生居家进行线上教学.学习.因为线上教学的各种局限性,为保证教学质量,学校要求老师们提前录制好课程,在上课时播放录制课程,老师自己需要在一旁进行线 ...

  9. Http2服务调用排坑记

    原文作者:陈友行原文链接:https://www.nginx.org.cn/article/detail/89转载来源:NGINX开源社区著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  10. Spring Boot中通过RabbitTemplate主动pull(get)消息的例子

    import java.util.Properties; import java.util.function.Consumer; import org.slf4j.Logger; import org ...