Sa-Token 权限注解
Sa-Token 是 JeecgBoot SpringBoot3 + Sa-Token 分支使用的权限框架。
分支地址:https://github.com/jeecgboot/JeecgBoot/tree/springboot3-satoken
概述
Sa-Token 是一个轻量级 Java 权限认证框架,主要解决登录认证、权限认证、单点登录、OAuth2、分布式 Session 等一系列权限相关问题。
常用权限注解
权限校验
@SaCheckPermission
要求用户拥有指定权限才能访问。
// 必须拥有指定权限
@SaCheckPermission("user:add")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<SysUser> add(@RequestBody SysUser user) {
userService.save(user);
return Result.ok("添加成功");
}
// 必须拥有多个权限(AND 关系)
@SaCheckPermission(value = {"user:add", "user:edit"}, mode = SaMode.AND)
@RequestMapping("/saveOrUpdate")
public Result<?> saveOrUpdate(@RequestBody SysUser user) {
userService.saveOrUpdate(user);
return Result.ok("保存成功");
}
// 拥有任一权限即可(OR 关系)
@SaCheckPermission(value = {"user:view", "user:list"}, mode = SaMode.OR)
@RequestMapping("/list")
public Result<?> list() {
return Result.ok(userService.list());
}
角色校验
@SaCheckRole
要求用户拥有指定角色才能访问。
// 必须拥有指定角色
@SaCheckRole("admin")
@RequestMapping("/delete")
public Result<?> delete(@RequestParam String id) {
userService.removeById(id);
return Result.ok("删除成功");
}
// 必须拥有多个角色(AND 关系)
@SaCheckRole(value = {"admin", "super"}, mode = SaMode.AND)
@RequestMapping("/systemConfig")
public Result<?> systemConfig() {
return Result.ok("系统配置");
}
// 拥有任一角色即可(OR 关系)
@SaCheckRole(value = {"admin", "manager"}, mode = SaMode.OR)
@RequestMapping("/audit")
public Result<?> audit() {
return Result.ok("审核页面");
}
其他注解
@SaCheckSafe
二级认证校验,用于一些敏感操作。
@SaCheckSafe
@RequestMapping("/transferMoney")
public Result<?> transferMoney() {
return Result.ok("转账成功");
}
@SaCheckBasic
HTTP Basic 认证校验。
@SaCheckBasic(account = "admin:123456")
@RequestMapping("/basicAuth")
public Result<?> basicAuth() {
return Result.ok("Basic 认证通过");
}
@SaCheckDisable
账号封禁校验。
@SaCheckDisable
@RequestMapping("/normalOperation")
public Result<?> normalOperation() {
return Result.ok("正常操作");
}
Sa-Token 注解参数说明
| 注解 | 说明 | 参数 |
|---|---|---|
@SaCheckLogin | 登录校验 | 无 |
@SaCheckPermission | 权限校验 | value: 权限标识mode: AND/OR 模式 |
@SaCheckRole | 角色校验 | value: 角色标识mode: AND/OR 模式 |
@SaCheckSafe | 二级认证校验 | value: 业务类型 |
@SaCheckBasic | HttpBasic 校验 | account: 账号password: 密码 |
@SaCheckDisable | 账号封禁校验 | value: 封禁服务类型 |
代码方式校验
除了注解方式,Sa-Token 还支持在代码中进行权限校验:
@RequestMapping("/complexAuth")
public Result<?> complexAuth() {
// 判断是否登录
if (!StpUtil.isLogin()) {
return Result.error("请先登录");
}
// 校验权限(无权限时抛出异常)
StpUtil.checkPermission("user:add");
// 校验角色(无角色时抛出异常)
StpUtil.checkRole("admin");
// 判断是否拥有权限(不抛出异常)
if (StpUtil.hasPermission("user:delete")) {
// 执行删除操作
}
// 判断是否拥有角色(不抛出异常)
if (StpUtil.hasRole("admin")) {
// 执行管理员操作
}
// 获取当前登录用户的 loginId(username)
String username = StpUtil.getLoginIdAsString();
// 获取当前登录用户的 Session
SaSession session = StpUtil.getSession();
return Result.ok("校验通过");
}
权限缓存清理
当用户权限变更时,需要清除权限缓存:
@Service
public class SysRoleServiceImpl implements ISysRoleService {
@Override
public void updateRole(SysRole role) {
// 更新角色信息
this.updateById(role);
// 清除相关用户的权限缓存
List<String> usernameList = getUsernamesByRoleId(role.getId());
StpInterfaceImpl.clearUserCache(usernameList);
}
@Override
public void updateUserRole(String userId) {
// 更新用户角色后,清除该用户的权限缓存
String username = userService.getUsernameById(userId);
StpInterfaceImpl.clearUserCache(Arrays.asList(username));
// 或者强制用户下线,重新登录
StpUtil.logout(username);
}
}
菜单配置权限标识
1. 打开系统菜单

2. 添加按钮权限
找到对应的列表,添加下级按钮权限:

3. 给角色分配权限
进入角色管理授权访问权限:

4. 生效说明
权限配置修改后,需要退出重新登录才能生效。
权限标识命名规范
模块:操作
例如:
user:add - 用户添加
user:edit - 用户编辑
user:delete - 用户删除
user:view - 用户查看
user:export - 用户导出
order:audit - 订单审核
最佳实践
1. 推荐使用注解方式
在 Controller 层使用注解进行权限控制,代码更清晰:
@RestController
@RequestMapping("/sys/user")
public class SysUserController {
@SaCheckPermission("user:add")
@PostMapping("/add")
public Result<?> add(@RequestBody SysUser user) {
return Result.ok(userService.save(user));
}
@SaCheckPermission("user:edit")
@PutMapping("/edit")
public Result<?> edit(@RequestBody SysUser user) {
return Result.ok(userService.updateById(user));
}
@SaCheckPermission("user:delete")
@DeleteMapping("/delete")
public Result<?> delete(@RequestParam String id) {
return Result.ok(userService.removeById(id));
}
}
2. 复杂权限判断使用代码方式
对于复杂的业务逻辑权限判断,建议在代码中处理:
@RequestMapping("/complexOperation")
public Result<?> complexOperation(@RequestParam String id) {
// 管理员可以操作所有数据,普通用户只能操作自己的数据
if (StpUtil.hasRole("admin") ||
(StpUtil.hasPermission("order:edit") && isOwner(id))) {
// 执行操作
return Result.ok("操作成功");
}
return Result.error("无权限操作");
}
3. 使用 OR 模式提高灵活性
// 拥有查看或列表权限之一即可访问
@SaCheckPermission(value = {"user:view", "user:list"}, mode = SaMode.OR)
@GetMapping("/query")
public Result<?> query() {
return Result.ok(userService.list());
}
常见问题
1. 注解不生效?
确保项目已重启,Sa-Token 注解配置需要重启后才能生效。
2. 权限配置后还是无法访问?
检查以下几点:
- 是否已在菜单管理中配置权限标识
- 是否已给角色分配该权限
- 是否已退出重新登录
- 权限标识是否拼写正确(区分大小写)
- 是否正确实现了
StpInterface接口
3. mode 参数的作用?
SaMode.AND:必须同时拥有所有指定的角色或权限SaMode.OR:只需拥有其中任一角色或权限即可
4. 权限缓存什么时候清除?
需要在以下情况手动清除权限缓存:
- 用户角色发生变化
- 角色权限发生变化
- 用户权限发生变化