一、引言:从业务痛点看 AOP 权限校验的价值

在企业级应用中,权限校验是几乎每个接口都绕不开的刚性需求。常见的做法是在每个业务方法开头写上一大段权限判断逻辑:

@GetMapping("/user/delete")
public Result deleteUser(@PathVariable Long id) {
    // 每个方法都要写一遍 —— 重复、冗余、易遗漏
    LoginUser user = UserContext.getCurrentUser();
    if (user == null || !user.hasPermission("user:delete")) {
        return Result.error(403, "无权限");
    }
    // 真正的业务逻辑...
}

这种方式的痛点显而易见:

  • 重复代码:每个接口都要写类似的校验模板
  • 容易遗漏:新增接口时可能忘记加校验,造成安全漏洞
  • 不易维护:权限规则变更时,需要逐个修改业务方法
  • 耦合度高:业务代码中混杂着权限校验逻辑

AOP(面向切面编程) 正是解决这类横切关注点(Cross-cutting Concerns)的标准方案。通过将权限校验抽取为独立的切面,我们可以做到:

  • 零业务侵入:业务方法只关注核心逻辑
  • 声明式权限:通过注解声明式地配置权限规则
  • 统一管理:所有权限逻辑集中维护
  • 易于扩展:新增校验规则只需修改切面

本文将从零开始,构建一套基于 Spring Boot + AOP + 注解 + JWT 的企业级权限校验方案。
在这里插入图片描述


二、整体设计:权限校验的执行流水线

在这里插入图片描述

2.1 核心流程概览

整个权限校验方案遵循「标记 → 拦截 → 解析 → 校验 → 放行/拦截」的执行流水线:

🌐 客户端请求

🚪 DispatcherServlet

🏷️ 方法是否标注
@RequiresPermission?

⚡ 直接执行业务方法

🛡️ AOP 环绕通知拦截

👤 从 UserContext 获取当前用户

👑 是否为超级管理员?

⏭️ ignoreSuperAdmin = true?

🔍 继续校验

🎭 角色校验
checkRoles

🔑 权限码校验
checkPermissions

✅ 校验通过?

❌ 抛出 PermissionException

🔧 全局异常处理器

🚫 返回统一 403 JSON

📦 返回业务结果

2.2 各组件职责

处理层

上下文层

拦截层

声明层

校验失败

@RequiresPermission
自定义注解

PermissionAspect
AOP 切面

@Order 1
优先于日志切面

UserContext
ThreadLocal 存储

JwtUtils
Token 解析

PermissionException
自定义异常

GlobalExceptionHandler
统一异常处理

2.3 设计原则

原则 说明
单一职责 切面只负责权限校验,业务方法只负责业务逻辑
开闭原则 新增权限规则通过扩展注解属性实现,无需修改切面核心逻辑
依赖倒置 切面依赖 UserContext 抽象,不直接依赖具体 Token 解析实现
关注点分离 通过 AOP 将横切关注点与核心业务逻辑分离

2.4 切面使用 @Order(1)

✅ 校验通过

❌ 校验失败

🌐 请求

🛡️ PermissionAspect
@Order(1)

📝 LogAspect
@Order(2)

🎯 Controller

🔧 全局异常处理器

🚫 返回 403

关键设计考量:权限切面优先于日志切面执行。如果用户无权限,请求在权限切面层即被拦截,不会进入日志切面和业务方法,避免:

  • 无权限请求污染业务日志
  • 不必要的性能开销(解析参数、记录日志等)

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐