
Sa-Token 注解鉴权完全指南用 SaCheckLogin 等注解优雅剥离业务与鉴权逻辑【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token导读本文聚焦 Sa-Token 框架的注解鉴权能力讲解如何通过SaCheckLogin、SaCheckRole、SaCheckPermission等注解将登录校验、角色校验、权限校验从业务代码中优雅剥离。你将掌握拦截器注册、校验模式AND/OR、角色权限双重 or 校验、SaIgnore忽略认证与SaCheckOr批量注解鉴权的完整实战写法并结合 SaInterceptor 源码理解其底层执行顺序。一、注解鉴权把校验从业务代码里拆开很多开发者使用代码式鉴权StpUtil.checkLogin()、StpUtil.checkRole(...)等时都会面临一个诉求希望把鉴权逻辑和业务逻辑分离开来。Sa-Token 的注解鉴权正是为此而生——在方法或类上打一个注解校验规则即声明式地挂在目标代码上业务方法内部保持纯粹。Sa-Token 共提供以下 9 个鉴权相关注解注解作用SaCheckLogin登录校验只有登录之后才能进入该方法SaCheckRole(admin)角色校验必须具有指定角色标识才能进入该方法SaCheckPermission(user:add)权限校验必须具有指定权限才能进入该方法SaCheckSafe二级认证校验必须二级认证之后才能进入该方法SaCheckHttpBasicHttpBasic 校验只有通过 HttpBasic 认证后才能进入该方法SaCheckHttpDigestHttpDigest 校验只有通过 HttpDigest 认证后才能进入该方法SaCheckDisable(comment)账号服务封禁校验校验当前账号指定服务是否被封禁SaCheckSignAPI 签名校验用于跨系统的 API 签名参数校验SaIgnore忽略校验被修饰的方法或类无需进行注解鉴权和路由拦截器鉴权以上注解的实现都集中在 sa-token-core 的 annotation 包下每个注解对应一个 handler 校验器位于该包的 handler 子目录由全局策略统一调度。关键前提Sa-Token 使用全局拦截器完成注解鉴权功能。为了不为项目带来不必要的性能负担拦截器默认处于关闭状态。因此你必须手动将 Sa-Token 的全局拦截器注册到项目中注解鉴权才会生效。二、注册拦截器开启注解鉴权的前置步骤以 SpringBoot 项目为例新建配置类SaTokenConfigure.javaConfiguration public class SaTokenConfigure implements WebMvcConfigurer { // 注册 Sa-Token 拦截器打开注解式鉴权功能 Override public void addInterceptors(InterceptorRegistry registry) { // 注册 Sa-Token 拦截器打开注解式鉴权功能 registry.addInterceptor(new SaInterceptor()).addPathPatterns(/**); } }保证此类被 SpringBoot 启动类扫描到即可如位于启动类同包或子包下或通过ComponentScan显式指定包路径。从源码看SaInterceptor 是一个实现了 Spring MVCHandlerInterceptor的全局拦截器它的核心执行流程如下preHandle方法执行beforeAuth前置函数在注解鉴权之前执行默认为空操作当isAnnotation为true且当前 handler 是HandlerMethod类型时调用SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method)完成注解鉴权执行auth路由拦截鉴权函数即后续 路由拦截鉴权 章节注册的setAuth(...)回调。其中isAnnotation字段控制注解鉴权开关默认trueSaInterceptor还提供isAnnotation(false)、setBeforeAuth(...)、setAuth(...)链式方法供需要自定义路由拦截场景时使用。三、使用注解鉴权九个注解的实战写法注册好拦截器后就可以直接在 Controller 方法上使用注解了// 登录校验只有登录之后才能进入该方法 SaCheckLogin RequestMapping(info) public String info() { return 查询用户信息; } // 角色校验必须具有指定角色才能进入该方法 SaCheckRole(super-admin) RequestMapping(add) public String add() { return 用户增加; } // 权限校验必须具有指定权限才能进入该方法 SaCheckPermission(user-add) RequestMapping(add) public String add() { return 用户增加; } // 二级认证校验必须二级认证之后才能进入该方法 SaCheckSafe() RequestMapping(add) public String add() { return 用户增加; } // Http Basic 校验只有通过 Http Basic 认证后才能进入该方法 SaCheckHttpBasic(account sa:123456) RequestMapping(add) public String add() { return 用户增加; } // Http Digest 校验只有通过 Http Digest 认证后才能进入该方法 SaCheckHttpDigest(value sa:123456) RequestMapping(add) public String add() { return 用户增加; } // 校验当前账号是否被封禁 comment 服务如果已被封禁会抛出异常无法进入方法 SaCheckDisable(comment) RequestMapping(send) public String send() { return 查询用户信息; }注意以上注解都可以加在类上代表为这个类的所有方法进行鉴权。仓库示例 AtCheckController.java 完整演示了登录鉴权、权限校验含 AND/OR 多权限、角色校验、角色权限双重 or 校验、SaIgnore忽略校验等场景可作为实战参考。3.1 注解的核心属性说明结合注解源码几个高频属性值得展开type多账号体系标识SaCheckLogin、SaCheckRole、SaCheckPermission、SaCheckSafe、SaCheckDisable均提供type属性默认用于多账号体系下指定所属的账号体系。非多账号体系无需关注此值。mode校验模式SaCheckRole与SaCheckPermission的value为数组配合mode默认SaMode.AND决定多个标识的校验关系。value校验标识SaCheckDisable的value默认值为SaTokenConsts.DEFAULT_DISABLE_SERVICE默认服务标识并额外提供level属性表示封禁等级——当账号被封禁等级 ≥ 该值时请求无法进入方法默认SaTokenConsts.DEFAULT_DISABLE_LEVEL。SaCheckSafe的value默认值为SaTokenConsts.DEFAULT_SAFE_AUTH_SERVICE即二级认证默认校验的服务标识。四、设定校验模式SaMode.AND 与 SaMode.ORSaCheckRole与SaCheckPermission注解可通过mode参数设定校验模式// 注解式鉴权只要具有其中一个权限即可通过校验 RequestMapping(atJurOr) SaCheckPermission(value {user-add, user-all, user-delete}, mode SaMode.OR) public SaResult atJurOr() { return SaResult.data(用户信息); }mode有两种取值见 SaMode.javaSaMode.AND标注一组权限会话必须全部具有才可通过校验SaMode.OR标注一组权限会话只要具有其一即可通过校验。默认值是AND即不写mode时value数组中的多个标识必须全部命中。当value只写一个标识时mode不产生差别。五、角色权限双重 or 校验orRole 的三种写法假设有以下业务场景一个接口在具有权限user.add或角色admin时可以调通。此时可用SaCheckPermission的orRole属性// 角色权限双重 or校验具备指定权限或者指定角色即可通过校验 RequestMapping(userAdd) SaCheckPermission(value user.add, orRole admin) public SaResult userAdd() { return SaResult.data(用户信息); }orRole字段代表权限校验未通过时的次要选择两者只要其一校验成功即可进入请求方法源码注释见 SaCheckPermission.java其有三种写法写法一orRole admin代表需要拥有角色admin写法二orRole {admin, manager, staff}代表具有三个角色其一即可写法三orRole {admin, manager, staff}代表必须同时具有三个角色。其中写法二与写法三的区别在于字符串数组元素的粒度写法二的每个元素是单个角色取 OR 关系写法三将多个角色写在同一个字符串内并以逗号分隔取 AND 关系。六、忽略认证SaIgnore 让接口对游客开放使用SaIgnore可表示一个接口忽略认证SaCheckLogin RestController public class TestController { // ... 其它方法 // 此接口加上了 SaIgnore 可以游客访问 SaIgnore RequestMapping(getList) public SaResult getList() { // ... return SaResult.ok(); } }如上代码表示TestController中的所有方法都需要登录后才可以访问但是getList接口可以匿名游客访问。使用SaIgnore时需注意三点SaIgnore修饰方法时代表这个方法可以被游客访问修饰类时代表这个类中的所有接口都可以游客访问SaIgnore具有最高优先级当SaIgnore和其它鉴权注解一起出现时其它鉴权注解都将被忽略SaIgnore同样可以忽略掉 Sa-Token 拦截器中的路由鉴权即 路由拦截鉴权 章节中setAuth(...)注册的校验函数。从源码看SaIgnore.java其忽略效果只针对SaInterceptor拦截器和 AOP 注解鉴权生效对自定义拦截器与过滤器不生效——如果你的项目额外注册了自定义拦截器做鉴权SaIgnore无法豁免它们。七、批量注解鉴权SaCheckOr 实现多条件任一通过使用SaCheckOr表示批量注解鉴权只要当前会话满足其中任意一个注解即可通过验证进入方法。// 在 SaCheckOr 中可以指定多个注解只要当前会话满足其中一个注解即可通过验证进入方法。 SaCheckOr( login SaCheckLogin, role SaCheckRole(admin), permission SaCheckPermission(user.add), safe SaCheckSafe(update-password), httpBasic SaCheckHttpBasic(account sa:123456), disable SaCheckDisable(submit-orders) ) RequestMapping(test) public SaResult test() { // ... return SaResult.ok(); }从 SaCheckOr.java 源码看其内部属性为数组形式包含login、role、permission、safe、httpBasic、httpDigest、disable七类注解属性以及append追加属性。因此每一项属性都可以写成数组形式例如// 当前客户端只要有 [ login 账号登录] 或者 [user 账号登录] 其一就可以通过验证进入方法。 // 注意type login 和 type user 是多账号模式章节的扩展属性此处你可以先略过这个知识点。 SaCheckOr( login { SaCheckLogin(type login), SaCheckLogin(type user) } ) RequestMapping(test) public SaResult test() { // ... return SaResult.ok(); }7.1 为什么没有 SaCheckAnd疑问既然有了SaCheckOr为什么没有与之对应的SaCheckAnd呢因为当你写多个注解时其天然就是and校验关系// 当你在一个方法上写多个注解鉴权时其默认就是要满足所有注解规则后才可以进入方法只要有一个不满足就会抛出异常 SaCheckLogin SaCheckRole(admin) SaCheckPermission(user.add) RequestMapping(test) public SaResult test() { // ... return SaResult.ok(); }7.2 使用 append 字段追加扩展包注解SaCheckOr还提供append字段用于追加抓取扩展包里的注解 Class只能是 Sa-Token 相关注解类型。例如配合 sa-token-apikey 插件的SaCheckApiKey// 测试只有通过登录校验或者提供了正确的 ApiKey才可以进入方法 RequestMapping(/test) SaCheckOr(login SaCheckLogin, append { SaCheckApiKey.class }) SaCheckApiKey public SaResult test() { // ... return SaResult.ok(); }八、原理速览注解如何被逐个校验在核心模块 sa-token-core 的测试目录下你可以找到SaCheckOrHandlerTest、SaAnnotationHandlerTest、SaAnnotationStrategyTest等测试用例它们验证了注解处理器与策略调度的核心行为。结合 annotation/handler 目录下的实现可以推断整体机制每个注解SaCheckLogin、SaCheckRole等对应一个SaCheckXxxHandler如 SaCheckLoginHandler.java、SaCheckOrHandler.java所有 handler 统一实现SaAnnotationHandlerInterface接口由SaAnnotationStrategy全局策略按注解类型路由到对应 handlerSaInterceptor在请求前置阶段拿到目标Method调用checkMethodAnnotation策略即触发对应 handler 的校验逻辑——校验失败抛出异常如NotLoginException、NotRoleException、NotPermissionException由全局异常处理器统一转为响应输出。九、扩展阅读在业务逻辑层Service 等任意层级使用鉴权注解AOP 注解鉴权制作自定义鉴权注解注入到框架自定义注解拦截器中的路由拦截鉴权setAuth(...)与SaIgnore的配合路由拦截鉴权完整可运行示例AtCheckController.java。附注注解鉴权与代码鉴权各有所长——代码式鉴权灵活、可动态控制校验条件注解式鉴权声明式、零侵入业务代码。实际项目中常两者混用类/方法级固定规则用注解动态分支内的校验用代码式二者底层共享同一套StpLogic校验逻辑行为完全一致。【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考