资讯动态

Sa-Token AOP 注解鉴权:突破 Controller 层限制,在任意层级使用鉴权注解

发布时间:2026/9/14 15:09:22 来源:尧图企业网站定制
Sa-Token AOP 注解鉴权突破 Controller 层限制在任意层级使用鉴权注解【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token导读Sa-Token 的注解式鉴权默认基于全局拦截器实现虽然简单优雅但存在一个明显的边界注解只能写在 Controller 层无法在 Service、工具类等业务层级进行校验。本指南介绍 Sa-Token 提供的 AOP 插件sa-token-spring-aop讲解如何在任意层级使用注解鉴权、其底层织入原理与注意事项。读完本文你将掌握把SaCheckLogin、SaCheckPermission等注解下沉到业务逻辑层进行校验的完整方案。一、为什么需要 AOP 注解鉴权Sa-Token 默认的注解鉴权由全局拦截器驱动。以 SpringBoot 项目为例需要在配置类中手动注册SaInterceptorConfiguration public class SaTokenConfigure implements WebMvcConfigurer { // 注册 Sa-Token 拦截器打开注解式鉴权功能 Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SaInterceptor()).addPathPatterns(/**); } }拦截器基于 Spring MVC 的HandlerInterceptor机制只对进入DispatcherServlet的 HTTP 请求生效。这意味着注解只能写在Controller层的方法或类上写在 Service、Manager 等更底层业务代码上的注解不会被执行无法对非 HTTP 调用链如内部任务调度、消息消费、定时任务中的业务方法进行注解校验。而在实际项目中某笔业务只有登录用户才能操作、某服务只有指定角色才能调用 这类约束往往横跨多个架构层。为此Sa-Token 提供了 Spring AOP 插件将注解校验织入到任意 Spring Bean 的方法调用中。二、引入依赖在pom.xml中添加以下依赖Gradle 工程请使用右侧对应的依赖写法!-- Sa-Token 整合 SpringAOP 实现注解鉴权 -- dependency groupIdcn.dev33/groupId artifactIdsa-token-spring-aop/artifactId version${sa.top.version}/version /dependency// Sa-Token 整合 SpringAOP 实现注解鉴权 implementation cn.dev33:sa-token-spring-aop:${sa.top.version}其中${sa.top.version}请替换为你当前项目使用的 Sa-Token 版本当前仓库根 pom.xml 中声明的版本为1.46.0。从插件模块的 pom.xml 可以看出该插件内部依赖了sa-token-core核心鉴权逻辑与spring-boot-starter-aopSpring AOP 能力因此它天然适用于 Spring 生态项目。引入依赖后无需额外编写任何配置类——插件通过 Spring Boot 自动装配机制完成切入点的注册这也是它与拦截器模式最大的体验差异。三、在任意层级使用注解鉴权引入依赖后Sa-Token 的所有鉴权注解SaCheckLogin、SaCheckRole、SaCheckPermission、SaCheckSafe、SaCheckHttpBasic、SaCheckHttpDigest、SaCheckDisable、SaIgnore等都可以直接标注在任意 Spring Bean 的方法或类上。3.1 方法级校验Service public class OrderService { // 登录校验只有登录之后才能执行该方法 SaCheckLogin public Order createOrder(OrderDTO dto) { // ... 业务逻辑 } // 权限校验必须具有 user:add 权限才能执行该方法 SaCheckPermission(user:add) public void addUser(User user) { // ... 业务逻辑 } // 角色校验必须具有 admin 角色才能执行该方法 SaCheckRole(admin) public void deleteOrder(Long id) { // ... 业务逻辑 } }当Controller调用这些 Service 方法时Spring AOP 会先执行注解校验校验通过后才进入方法体未通过则抛出对应异常如NotLoginException、NotPermissionException等由全局异常处理器统一捕获。3.2 类级校验与 SaIgnore 局部豁免注解同样可以标注在类上代表对该类的所有方法进行鉴权Service SaCheckLogin public class UserService { // 该类的所有方法都需要登录后才能执行 public User getById(Long id) { ... } // 方法上的 SaIgnore 可以跳过类上的鉴权允许游客访问 SaIgnore public ListUser listPublic() { ... } }这一行为与 Controller 层的规则完全一致SaIgnore具有最高优先级当它与其他鉴权注解同时出现时其他鉴权注解都会被忽略。3.3 权限/角色注解的校验模式SaCheckRole与SaCheckPermission支持SaMode校验模式// 只要具有其中一个权限即可通过校验 SaCheckPermission(value {user-add, user-all, user-delete}, mode SaMode.OR) public SaResult atJurOr() { return SaResult.data(用户信息); }SaMode.AND必须同时满足全部权限/角色才可通过SaMode.OR满足其中任意一个即可通过。还支持权限与角色的双重 or 校验// 具备 user.add 权限或者 admin 角色即可通过校验 SaCheckPermission(value user.add, orRole admin) public SaResult userAdd() { return SaResult.data(用户信息); }orRole有三种写法admin拥有 admin 角色、{admin, manager}拥有其一、{admin, manager}必须同时拥有。四、AOP 模式底层原理三个类织入一次校验AOP 模式的核心代码位于插件模块的cn.dev33.satoken.aop包下由三个类协作完成4.1 切入点注册SaAopPointcutAdvisorBeanRegisterSaAopPointcutAdvisorBeanRegister.java 是一个Configuration类通过Bean方法向 Spring 容器注册了一个SaAroundAnnotationPointcutAdvisor使用AspectJExpressionPointcut动态计算切入表达式表达式由SaAnnotationStrategy.instance.annotationHandlerMap中注册的所有注解类拼接而成格式为within(cn.dev33.satoken.annotation.SaCheckLogin) || annotation(cn.dev33.satoken.annotation.SaCheckLogin) || within(cn.dev33.satoken.annotation.SaCheckRole) || annotation(cn.dev33.satoken.annotation.SaCheckRole) || within(cn.dev33.satoken.annotation.SaCheckPermission) || annotation(cn.dev33.satoken.annotation.SaCheckPermission) || ...其中within(X)匹配类上标注了 X 注解的所有方法annotation(X)匹配方法上标注了 X 注解的方法。这解释了为什么Service 方法、甚至类上标注的注解都能被捕捉到——切点不再依赖 MVC 拦截链而是由 Spring AOP 对 Bean 方法直接织入。该注册类还会收集容器中所有实现了SaAnnotationHandlerInterface?的额外注解处理器ListSaAnnotationHandlerInterface? handlerList将它们的注解类型一并追加进切点表达式从而实现自定义鉴权注解的 AOP 化支持。4.2 环绕通知SaAroundAnnotationMethodInterceptorSaAroundAnnotationMethodInterceptor.java 实现了 AOP Alliance 的MethodInterceptor在每个被切中的方法执行前调用核心策略Override public Object invoke(MethodInvocation invocation) throws Throwable { // 注解鉴权 try { Method method invocation.getMethod(); SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method); } catch (StopMatchException ignored) { } // 执行原有方法 return invocation.proceed(); }可见 AOP 模式并没有复制一套注解解析逻辑而是复用核心包中拦截器模式同一套校验入口checkMethodAnnotation只是把触发时机从HTTP 请求进入 Controller换成了Spring 调用任意 Bean 方法保证了两种模式在校验规则上的一致性。4.3 核心校验调用链SaAnnotationStrategy.java 中checkMethodAnnotation的默认实现依次完成三件事若方法或其所属类标注了SaIgnore调用SaRouter.stop()跳过整个校验先校验方法所属类上的注解method.getDeclaringClass()再校验方法自身上的注解。随后checkElementAnnotation遍历annotationHandlerMap中注册的注解处理器内置了SaCheckLoginHandler、SaCheckRoleHandler、SaCheckPermissionHandler、SaCheckSafeHandler、SaCheckDisableHandler、SaCheckHttpBasicHandler、SaCheckHttpDigestHandler、SaCheckOrHandler等命中哪个注解就调用对应的handler.check()执行校验。这就是为什么 AOP 模式能支持与拦截器模式完全相同的全部注解。4.4 自动装配验证从源码结构看插件通过ConfigurationBean自动注册 Advisor无需手动声明配置类。仓库测试 SaAopAutoConfigurationSpringTest.java 对此给出了直接验证autoConfig_registersAdvisor断言 Advisor 已自动装配并挂到静态字段SaAopPointcutAdvisorBeanRegister.saAroundAnnoAdvisor上且切点表达式同时包含内置注解SaCheckLogin与追加的自定义注解ExtraCheckmethodLevel_checkLoginService 方法上标注SaCheckLogin未登录时抛出NotLoginException登录后放行classLevel_checkLogin类上标注SaCheckLogin验证within切点未登录拦截、登录后放行saIgnore_skipsCheck类上有登录校验时方法上的SaIgnore可跳过鉴权extraHandler_isWoven在容器中注册的自定义注解处理器会被织入切点并真正执行校验逻辑。配套的业务 Bean 见 MethodLoginService.java方法级注解与 ClassLoginService.java类级注解 SaIgnore可作为你落地时的参考范例。五、注意事项拦截器模式与 AOP 模式不可同时集成。如果同时注册SaInterceptor与sa-token-spring-aop插件Controller 层的方法会被校验两次一次来自 Spring AOP 环绕通知一次来自 MVC 拦截器可能导致同一接口重复鉴权甚至二次放行异常。二选一即可。AOP 模式不能替代路由拦截鉴权。AOP 插件只负责注解校验若你还需要基于StpUtil/SaRouter的路由式拦截鉴权如按 URL 批量放行、动态路由规则仍需配合拦截器或过滤器实现详见路由拦截鉴权。仅对 Spring Bean 方法生效。AOP 织入基于 Spring 代理被代理的只能是容器管理的 Bean直接new出来的对象或非 Spring 调用链不会触发校验。同时要注意同类内部方法自调用this.method()不会经过代理如需对内部调用也生效应通过注入自身的代理对象调用。异常处理。AOP 模式下校验失败同样抛出对应的 Sa-Token 异常如NotLoginException、NotPermissionException、NotRoleException等请确保全局异常处理器能统一捕获避免异常被吞掉导致接口静默失败。六、总结对比项拦截器模式AOP 模式sa-token-spring-aop依赖内置无需额外引入引入sa-token-spring-aop生效层级仅 Controller 层任意 Spring Bean 层级触发机制Spring MVCHandlerInterceptorSpring AOP 环绕通知配置方式手动注册SaInterceptor自动装配零配置校验规则SaAnnotationStrategy.checkMethodAnnotation与拦截器模式完全一致同一入口两者共存—不可同时集成否则 Controller 层会校验两次AOP 注解鉴权是 Sa-Token 注解体系的自然延伸它不改变任何注解的写法与校验规则只是将触发点从 MVC 拦截器迁移到 Spring AOP 代理从而让SaCheckLogin、SaCheckPermission等注解下沉到 Service 等任意业务层级。核心校验逻辑统一收敛在 SaAnnotationStrategy 的策略函数中两种模式共享同一套注解解析与处理器分发机制保证了规则的一致性与可扩展性。需要让注解发挥更大作用域的 Spring 项目可直接按上文引入插件使用。【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价