AOP实现权限校验
在实际开发中,我们常常需要对接口进行权限控制。传统做法是在方法内部进行权限判断,这样做不仅代码冗余、耦合度高,还违背了单一职责原则。为了解耦权限逻辑与业务代码,我们可以借助 AOP(面向切面编程) 实现权限校验,搭配自定义注解,使权限控制更加灵活优雅。
一、什么是 AOP?
AOP(Aspect Oriented Programming),即面向切面编程,是 Spring 框架中用于封装横切关注点(如日志、事务、安全等)的一种技术。
简单来说,它可以在不修改原始业务逻辑的前提下,对方法的执行过程进行增强,如:
- 方法执行前后插入逻辑
- 异常处理
- 条件拦截执行等
二、自定义注解的原理
自定义注解是 Java 提供的一种元编程方式,可以在代码中通过标记注解,传递元信息。结合 AOP,我们可以读取这些注解,并据此决定是否拦截某个方法、执行特定逻辑,从而实现解耦和代码复用。
三、代码实现,引入 AOP 依赖
首先需要在 pom.xml 中引入 Spring AOP 的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
四、编写权限注解
我们自定义一个注解 @AuthCheck,用于标记需要权限校验的方法:
/**
* 权限校验注解
*
* 用于指定访问该方法所必须拥有的角色。
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {
/**
* 指定访问该方法所需的角色,例如:admin
*/
String mustRole() default "";
}
使用时,只需在方法上加上 @AuthCheck(mustRole = "admin") 即可。
五、实现权限拦截器(切面类)
创建一个切面类 AuthInterceptor,用于在方法执行前进行权限校验:
@Aspect
@Component
public class AuthInterceptor {
@Resource
private UserService userService;
/**
* 环绕通知,拦截标记了 @AuthCheck 注解的方法
*
* @param joinPoint 切入点
* @param authCheck 注解信息
*/
@Around("@annotation(authCheck)")
public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
String mustRole = authCheck.mustRole();
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
// 获取当前登录用户
User loginUser = userService.getCurrentLoginUser(request);
// 将注解中的角色值转为枚举
UserRoleEnum mustRoleEnum = UserRoleEnum.getUserRoleByValue(mustRole);
// 如果注解未指定角色,直接放行
if (mustRoleEnum == null) {
return joinPoint.proceed();
}
// 获取当前用户的角色
UserRoleEnum userRoleEnum = UserRoleEnum.getUserRoleByValue(loginUser.getUserRole());
// 若用户无权限,抛出异常
if (userRoleEnum == null) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
// 若要求管理员权限,但当前用户不是管理员,拒绝访问
if (UserRoleEnum.ADMIN.equals(mustRoleEnum) && !UserRoleEnum.ADMIN.equals(userRoleEnum)) {
throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
}
// 校验通过,执行原方法
return joinPoint.proceed();
}
}
六、使用示例
@AuthCheck(mustRole = "admin")
@GetMapping("/admin/data")
public Result<List<Data>> getAdminData() {
// 仅管理员可访问
return Result.success(dataService.getSensitiveData());
}
七、小结
通过 AOP + 自定义注解,可以让权限校验逻辑与业务代码彻底解耦,具备以下优势:
- 灵活扩展:支持自定义不同角色逻辑;
- 复用性高:统一拦截逻辑,减少代码重复;
- 增强可读性:方法上直接标注权限要求,一目了然;
- 更易维护:权限逻辑集中管理,排查问题更方便。
贡献者
flycodeu
版权所有
版权归属:flycodeu