news 2026/4/19 20:55:22

剖析 Sa-Token (三) 权限认证的注解驱动与拦截器协同

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
剖析 Sa-Token (三) 权限认证的注解驱动与拦截器协同

1. 注解驱动的权限认证设计原理

第一次看到@SaCheckPermission注解时,我盯着那个小小的@符号发了半天呆——就这么个简单的标记,居然能自动完成权限校验?这背后到底藏着什么魔法?后来在项目里踩过几次坑才明白,注解本质上就是个"标记牌",真正干活的其实是藏在幕后的拦截器。

Sa-Token的权限注解支持四种关键参数配置:

  • value:权限码数组,支持多个权限同时校验
  • mode:验证模式,AND表示需同时具备所有权限,OR表示具备任一即可
  • type:多账号体系标识,适合复杂权限系统
  • orRole:权限不满足时的备选角色方案

举个例子,下面这个配置就很有意思:

@SaCheckPermission( value = "user:delete", mode = SaMode.OR, orRole = {"admin", "super-admin"} ) public void deleteUser() { // 删除用户操作 }

这表示调用该方法需要满足:要么有user:delete权限,要么具备admin或super-admin角色。我在电商项目里就用这种组合方案,既保证了权限粒度,又避免了给高管分配过多具体权限。

2. 拦截器如何捕获注解信息

记得第一次调试SaAnnotationInterceptor时,我在preHandle方法里打了断点。当请求进来时,看到handler对象居然能转换成HandlerMethod,当时就觉得Spring的设计真巧妙。这个拦截器的工作流程其实很清晰:

  1. 将handler强制转换为HandlerMethod获取方法对象
  2. 把方法对象丢给SaStrategy做注解检查
  3. 通过验证就放行,不通过就抛出异常

关键代码其实就三行:

if (handler instanceof HandlerMethod == false) return true; Method method = ((HandlerMethod) handler).getMethod(); SaStrategy.me.checkMethodAnnotation.accept(method);

但这里有个坑我踩过——如果Controller里混用了普通请求和WebSocket等特殊请求,记得要做类型判断。有次线上事故就是因为没判断handler类型,导致WebSocket连接被错误拦截。

3. 策略模式在权限校验中的应用

SaStrategy这个类名起得特别到位,它确实把校验策略玩出了花。看它的checkByAnnotation方法,会根据注解配置选择不同验证策略:

if(at.mode() == SaMode.AND) { this.checkPermissionAnd(permissionArray); } else { this.checkPermissionOr(permissionArray); }

最精妙的是它对异常的处理——当权限校验失败时,还会尝试检查orRole配置的角色:

catch (NotPermissionException e) { if(at.orRole().length > 0) { // 尝试角色校验 } throw e; }

这种设计让权限系统既严格又灵活。我在金融项目里就用这个特性实现了"权限不够角色补"的机制,风控部门的同事再也不用频繁申请临时权限了。

4. 权限数据的获取链路解析

追查getPermissionList方法时,我发现了个有趣的设计。SaManager并没有直接持有权限数据,而是通过StpInterface接口获取:

public List<String> getPermissionList(Object loginId) { return SaManager.getStpInterface().getPermissionList(loginId, loginType); }

这种解耦设计让数据源可以灵活替换。有次需要从Redis获取权限,我只花了半小时就实现了自定义的StpInterface:

public class RedisStpInterface implements StpInterface { @Override public List<String> getPermissionList(Object loginId, String loginType) { // 从Redis获取权限列表 } }

更妙的是SaManager的自动装配机制。通过@Autowired自动注入实现类,连配置文件都不用改:

@Autowired(required = false) public void setStpInterface(StpInterface stpInterface) { SaManager.setStpInterface(stpInterface); }

5. 实战中的典型问题排查

在微服务环境下,我遇到过注解不生效的情况。后来发现是拦截器顺序问题,Spring的拦截器链是有执行顺序的。解决方法是在配置类里加上:

@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SaAnnotationInterceptor()) .addPathPatterns("/**") .order(Ordered.HIGHEST_PRECEDENCE); }

另一个常见问题是权限缓存更新。当用户权限变更时,记得调用StpUtil.getPermissionList()的重载方法强制刷新:

// 强制从数据源重新加载 List<String> permissions = StpUtil.getPermissionList(userId, true);

有次线上权限失效,就是因为忘了这个参数,导致用户权限变更后依然读取旧缓存。现在我的团队都养成了习惯——所有权限修改操作后必须主动清除缓存。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 20:53:01

因果推断实战:从理论到三大核心方法解析

1. 因果推断&#xff1a;从关联到因果的思维跃迁 第一次接触因果推断时&#xff0c;我和大多数数据科学从业者一样困惑&#xff1a;为什么在机器学习大行其道的今天&#xff0c;我们还需要研究这个看似"古老"的统计学概念&#xff1f;直到在一次医疗数据分析项目中&a…

作者头像 李华
网站建设 2026/4/19 20:52:28

2026最权威的六大AI科研工具横评

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 在人工智能生成内容越来越普遍的情形下&#xff0c;降AI工具顺势出现了&#xff0c;它存在的…

作者头像 李华
网站建设 2026/4/19 20:51:17

灵活的使用ap_ctlr_none实现功能(二)

一、h文件设计 #ifndef FRAME_TOP_H_ #define FRAME_TOP_H_ //#include "ap_int.h" #include "hls_stream.h" #include "ap_axi_sdata.h" // 定义带边带信号的 AXI4-Stream 数据类型 // 数据宽度 24 位(RGB888),用户自定义宽度为 1(用于 …

作者头像 李华
网站建设 2026/4/19 20:50:16

告别鼠标手:用键盘精准控制光标的效率神器Mouseable

告别鼠标手&#xff1a;用键盘精准控制光标的效率神器Mouseable 【免费下载链接】mouseable Mouseable is intended to replace a mouse or trackpad. 项目地址: https://gitcode.com/gh_mirrors/mo/mouseable 你是否厌倦了长时间使用鼠标导致的手腕酸痛&#xff1f;是否…

作者头像 李华