Sa-Token Thymeleaf 标签方言:在页面中优雅实现登录、角色与权限控制
【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架,让鉴权变得简单、优雅!—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token
本篇文章讲解 Sa-Token 官方插件sa-token-thymeleaf的完整用法:如何把它引入 Thymeleaf 模板引擎、如何注册标签方言 Bean、如何使用sa:前缀下的登录判断 / 角色判断 / 权限判断标签,以及如何通过注入全局变量stp在页面中直接调用 Sa-Token 的底层 API。读完本文,你将能够在 Thymeleaf 页面中零 Java 代码地完成大部分鉴权显隐控制,并理解每个标签背后的实现原理。
1、标签方言是什么
Sa-Token 的核心能力(登录认证、角色认证、权限认证)默认是在 Java 层通过StpUtil调用的。但在 Web 开发中,很多鉴权需求发生在视图层:例如"登录用户才能看到这段内容""只有 admin 角色才能看到管理按钮""没有 user-add 权限就不渲染新增按钮"。
sa-token-thymeleaf插件为 Thymeleaf 提供了一套自定义标签方言(Dialect),让你可以直接在 HTML 标签属性上写sa:login、sa:hasRole="admin"这类指令。模板渲染时,Thymeleaf 引擎会根据当前登录状态动态决定保留或移除对应元素,从而实现页面级的权限控制,无需编写任何 Java 判断逻辑。
从源码看,该方言由三个文件构成:
- SaTokenDialect.java:方言主体,继承 Thymeleaf 的
AbstractProcessorDialect,注册全部标签处理器; - SaTokenTagProcessor.java:属性标签处理器,负责执行判断表达式并按结果保留/移除元素;
- Sa-Token-Dialect.xml:方言描述文件,声明命名空间与各属性的说明文档。
2、引入依赖
首先确保项目已经引入 Thymeleaf 依赖(Spring Boot 项目通常使用spring-boot-starter-thymeleaf),然后在此基础上继续添加sa-token-thymeleaf插件。
Maven 方式:
<!-- 在 thymeleaf 标签中使用 Sa-Token --> <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-thymeleaf</artifactId> <version>${sa.top.version}</version> </dependency>Gradle 方式:
// 在 thymeleaf 标签中使用 Sa-Token implementation 'cn.dev33:sa-token-thymeleaf:${sa.top.version}'说明:
${sa.top.version}是 Sa-Token 版本号占位符,请替换为你实际使用的版本。仓库中的演示工程 sa-token-demo-thymeleaf/pom.xml 使用的是1.46.0,可作参考。
从插件自身的 pom.xml 可以看到,它仅依赖sa-token-core(Sa-Token 核心)与thymeleaf(且标记为optional),不会引入多余的传递依赖,非常轻量。
3、注册标签方言对象
依赖引入后,需要在 Spring 配置类中把SaTokenDialect注册为 Bean,Thymeleaf 才能识别并启用这套方言。
在SaTokenConfigure配置类中注册 Bean:
@Configuration public class SaTokenConfigure { // Sa-Token 标签方言 (Thymeleaf版) @Bean public SaTokenDialect getSaTokenDialect() { return new SaTokenDialect(); } }仓库演示工程中的 SaTokenConfigure.java 就是完全一致的写法。
关于底层 StpLogic(源码细节):SaTokenDialect有两个构造方法。无参构造内部实际调用的是this("sa", 1000, StpUtil.stpLogic),即默认方言名称为sa、处理器优先级为1000、底层复用StpUtil的全局StpLogic;你也可以通过new SaTokenDialect(name, precedence, stpLogic)自定义方言名称、优先级和所绑定的StpLogic(适用于多账号体系,让不同页面绑定不同登录体系)。这一点在 SaTokenDialectTest.java 的defaultConstructor_usesSaPrefixAndGlobalStpLogic与customConstructor_keepsNameAndPrecedence两个测试用例中得到了直接验证。
4、使用标签方言
注册完成后,就可以在 Thymeleaf 页面中直接使用sa:前缀的标签了。所有标签都会在渲染时执行一次判断:条件满足则保留元素(并把sa:属性从标签上移除),条件不满足则整个元素(连同其子内容)被删除,这是 Thymeleaf 自定义属性处理器SaTokenTagProcessor.doProcess中structureHandler.removeElement()的行为,详见 SaTokenTagProcessor.java。
4.1、登录判断
<h2>标签方言测试页面</h2> <p> 登录之后才能显示: <span sa:login>value</span> </p> <p> 不登录才能显示: <span sa:notLogin>value</span> </p>sa:login:当前账号已登录时显示该元素;sa:notLogin:当前账号未登录时显示该元素。
这两个标签底层调用的是stpLogic.isLogin()(见 SaTokenDialect.java),login取真值显示、notLogin取反后显示。
4.2、角色判断
<p> 具有角色 admin 才能显示: <span sa:hasRole="admin">value</span> </p> <p> 同时具备多个角色才能显示: <span sa:hasRoleAnd="admin, ceo, cto">value</span> </p> <p> 只要具有其中一个角色就能显示: <span sa:hasRoleOr="admin, ceo, cto">value</span> </p> <p> 不具有角色 admin 才能显示: <span sa:notRole="admin">value</span> </p>sa:hasRole="admin":具有指定角色才显示;sa:hasRoleAnd="admin, ceo, cto":同时具备多个角色才显示(多个值用逗号分隔);sa:hasRoleOr="admin, ceo, cto":只要具备其中任一角色就显示;sa:notRole="admin":不具有指定角色才显示。
从源码看,多角色/多权限值会先经过SaTokenDialect.toArray(value)转换成字符串数组,内部使用SaFoxUtil.convertStringToList按逗号切分并自动去除空格,因此"admin, ceo, cto"与"admin,ceo,cto"等价;对应测试toArray_splitsAndTrims也验证了" admin , user "会被正确解析为["admin", "user"]。
另外,方言 XML 描述文件 Sa-Token-Dialect.xml 中还声明了一个sa:lackRole属性,语义与notRole相同("不具有指定角色才能显示元素"),但文档标注为"未来版本可能废弃,建议更换为 notRole"。同理还有sa:lackPermission对应notPermission。新项目建议直接使用notRole/notPermission。
4.3、权限判断
<p> 具有权限 user-add 才能显示: <span sa:hasPermission="user-add">value</span> </p> <p> 同时具备多个权限才能显示: <span sa:hasPermissionAnd="user-add, user-delete, user-get">value</span> </p> <p> 只要具有其中一个权限就能显示: <span sa:hasPermissionOr="user-add, user-delete, user-get">value</span> </p> <p> 不具有权限 user-add 才能显示: <span sa:notPermission="user-add">value</span> </p>sa:hasPermission="user-add":具有指定权限才显示;sa:hasPermissionAnd="user-add, user-delete, user-get":同时具备全部权限才显示;sa:hasPermissionOr="user-add, user-delete, user-get":具备其中任一权限就显示;sa:notPermission="user-add":不具有指定权限才显示。
权限数据的来源由项目中的StpInterface实现类提供。仓库演示工程 StpInterfaceImpl.java 模拟返回了user-add、user-delete等权限码集合以及admin、super-admin角色集合,可对照理解标签判断的数据从何而来。
4.4、渲染行为验证(测试用例)
仓库在 SaTokenDialectTest.java 中对全部标签的显隐行为做了完整测试,例如:
hasRoleTag_rendersOrRemoves:拥有admin角色时<div>保留,只有user角色时整个元素被移除;hasRoleAndTag_requiresAllRoles:sa:hasRoleAnd="admin,ops"要求两个角色齐全才显示;hasRoleOrTag_requiresAnyRole:sa:hasRoleOr="admin,ops"只要具备其一即可;hasRoleTag_hiddenWhenNotLogin:未登录时hasRole等标签一律隐藏(内部通过捕获NotLoginException返回 false),这个行为非常实用,避免未登录页面暴露敏感区域;getProcessors_registers13Processors:方言共注册 13 个处理器(12 个鉴权标签 + 1 个用于移除<html>命名空间声明的处理器)。
5、在页面中调用 Sa-Token 相关 API
标签方言可以满足大多数场景下的权限判断。但有时候我们依然需要更加灵活地在页面中调用 Sa-Token 框架 API,例如读取SaSession中存放的业务数据、获取当前登录账号 ID 等。此时可以借助 Thymeleaf 的全局静态变量机制,把StpLogic暴露给页面。
首先在SaTokenConfigure配置类中为 Thymeleaf 配置全局对象:
@Configuration public class SaTokenConfigure{ // ... 其它代码 // 为 Thymeleaf 注入全局变量,以便在页面中调用 Sa-Token 的方法 @Autowired private void configureThymeleafStaticVars(ThymeleafViewResolver viewResolver) { viewResolver.addStaticVariable("stp", StpUtil.stpLogic); } }[!WARNING| label:注意] 如果
SaTokenConfigure继承了WebMvcConfigurer等类,可能会造成循环依赖,如果遇到,请新建一个其他配置类完成此项配置。
然后就可以在页面上调用StpLogic的 API 了,例如:
<p>调用 StpLogic 方法调用测试</p> <p th:if="${stp.isLogin()}"> 从SaSession中取值: <span th:text="${stp.getSession().get('name')}"></span> </p>这里stp即StpUtil.stpLogic,因此在页面中stp.isLogin()、stp.getSession().get('name')、stp.getLoginId()等StpLogic的公开方法都可以直接调用,与 Java 层的StpUtil完全同源。StpLogic是整个 Sa-Token 登录逻辑门面的实现类,多账号体系下每个 loginType 对应一个独立的StpLogic实例,这也是方言构造方法接受StpLogic参数的意义所在。
6、代码提示
如果想在写标签属性时获得 IDE 的代码提示(补全sa:login、sa:hasRole等属性),只需在 HTML 头部声明增加上对应的命名空间即可:
<!DOCTYPE html> <html lang="zh" xmlns:sa="http://www.thymeleaf.org/extras/sa-token"> <head> <!-- 代码 --> </head> <body> <!-- 代码 --> </body> </html>命名空间http://www.thymeleaf.org/extras/sa-token与方言描述文件 Sa-Token-Dialect.xml 中声明的namespace-uri保持一致。声明命名空间属于纯提示性质,即使不写,标签在运行时也能正常工作。
7、常用标签速查表
| 标签属性 | 底层调用(基于StpLogic) | 显示条件 |
|---|---|---|
sa:login | isLogin() | 已登录 |
sa:notLogin | !isLogin() | 未登录 |
sa:hasRole="admin" | hasRole("admin") | 具有指定角色 |
sa:hasRoleAnd="a, b" | hasRoleAnd([a, b]) | 同时具备全部角色 |
sa:hasRoleOr="a, b" | hasRoleOr([a, b]) | 具备任一角色 |
sa:notRole="admin" | !hasRole("admin") | 不具有指定角色 |
sa:lackRole="admin" | !hasRole("admin") | 同notRole(建议使用notRole) |
sa:hasPermission="user-add" | hasPermission("user-add") | 具有指定权限 |
sa:hasPermissionAnd="a, b" | hasPermissionAnd([a, b]) | 同时具备全部权限 |
sa:hasPermissionOr="a, b" | hasPermissionOr([a, b]) | 具备任一权限 |
sa:notPermission="user-add" | !hasPermission("user-add") | 不具有指定权限 |
sa:lackPermission="user-add" | !hasPermission("user-add") | 同notPermission(建议使用notPermission) |
8、小结
sa-token-thymeleaf插件以 Thymeleaf 自定义方言的形式,把 Sa-Token 的登录、角色、权限三大鉴权能力无缝下沉到视图层,让你在 HTML 中即可完成精细的显隐控制,同时通过stp全局变量保留了调用StpLogic全量 API 的灵活性。其实现路径清晰:SaTokenDialect负责注册处理器,SaTokenTagProcessor负责按判断结果渲染或移除元素,方言测试 与 演示工程 提供了可直接运行的参考。如果你是 Spring Boot + Thymeleaf 技术栈,这套标签方言能显著简化页面级权限控制的代码量。
【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架,让鉴权变得简单、优雅!—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考