spring aop结合自定义注解实现权限校验,通过@around切面统一拦截、支持and/or逻辑、角色与权限码混用、超级管理员豁免,并封装跨环境安全上下文及全局异常处理。

用 Spring AOP 结合自定义注解做权限校验,核心是把权限逻辑从业务代码里抽出来,统一在切面里判断——方法执行前拦住非法调用,不满足条件直接拒绝,不进业务层。
定义灵活的权限注解
注解要支持真实业务场景:多权限组合、AND/OR 逻辑、角色和权限码混用、超级管理员豁免。不能只写一个字符串值。
- 用 @Target({METHOD, TYPE}) 允许标注在接口或类上,覆盖更广
- 声明 String[] value() 存权限码,如
{"user:read", "order:export"} - 加 Logical logical() default Logical.AND 枚举控制校验逻辑
- 可选 String[] roles() 支持角色维度校验,比如
roles = {"admin", "manager"} - 加 boolean ignoreSuperAdmin() default true 控制是否跳过 super_admin 校验
用 @Around 实现可控拦截
@Before 拦不住方法执行,权限失败后业务代码照常跑;必须用 @Around,它能决定要不要放行、怎么返回、怎么抛异常。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 方法签名必须接收 ProceedingJoinPoint 和注解实例(如
RequiresPermission perm) - 先调 SecurityContext.getCurrentUserId() 取用户 ID,再查数据库或缓存拿到该用户全部角色+权限集合
- 根据
perm.logical()走 AND 或 OR 判断:AND 要全命中,OR 有一个就行 - 若用户是 super_admin 且
perm.ignoreSuperAdmin()为 true,直接joinPoint.proceed() - 不通过就 throw AccessDeniedException("无访问权限"),别吞异常
安全上下文要跨环境可靠
RequestContextHolder 在 WebFlux、@Async、定时任务里会失效,硬依赖它会导致 NPE 或权限漏判。
- 封装统一的 SecurityContext 工具类:优先尝试 ReactiveSecurityContextHolder(WebFlux),再 fallback 到 SecurityContextHolder(MVC),最后解析 ThreadLocal 中的 JWT token
- 所有切面、Service、工具类都只调
SecurityContext.getCurrentUserId(),不直取 RequestContextHolder - 异步方法需显式传递上下文,比如用
SecurityContext.wrap(Runnable)包装任务
配套统一异常与响应体
权限失败不能返回 500 或堆栈,要给前端明确、结构化的错误提示。
- 全局异常处理器捕获 AccessDeniedException,返回 HTTP 403 + 自定义 JSON,如
{"code":403,"msg":"缺少 order:delete 权限"} - 避免在切面里 new ResponseBody,交给 ControllerAdvice 统一格式化
- 日志切面建议加 @Order(1),确保权限校验早于日志记录,防止非法请求也被记日志
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










