跳到主要内容

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: 业务类型
@SaCheckBasicHttpBasic 校验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. 权限缓存什么时候清除?

需要在以下情况手动清除权限缓存:

  • 用户角色发生变化
  • 角色权限发生变化
  • 用户权限发生变化

相关文档