[Java][SpringBoot]AspectJ切面配合自定义注解实现权限校验

本文章介绍了如何通过创建自定义的权限校验注解,配合AspectJ切面拦截注解实现权限校验。

1. 创建权限校验注解

创建权限校验注解,可用在方法和类上,authPoint属性表示所需的权限点。代码如下:

java 复制代码
package com.guo.demo.examples.permissioncheck;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.METHOD})
public @interface PermissionCheck {
    /**
     * 所需的权限点
     *
     * @return 所需的权限点
     */
    String authPoint();
}

2. 创建AspectJ切面拦截注解校验权限

创建AspectJ切面,拦截带有@PermissionCheck注解的方法或类,获取注解上的权限点进行校验。代码如下:

java 复制代码
package com.guo.demo.examples.permissioncheck;

import lombok.extern.slf4j.Slf4j;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Slf4j
@Aspect
@Component
public class PermissionCheckAspect {
    // 权限校验服务
    @Resource
    private PermissionService permissionService;

    // 定义切入点表达式,匹配带有PermissionCheck注解的方法或类
    @Pointcut("@annotation(com.guo.demo.examples.permissioncheck.PermissionCheck) || @within(com.guo.demo.examples.permissioncheck.PermissionCheck)")
    public void pointCut() {
    }

    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 1.获取目标类上的目标注解
        PermissionCheck annotationInClass = AnnotationUtils.findAnnotation(signature.getDeclaringType(), PermissionCheck.class);
        // 2.获取目标方法上的目标注解
        PermissionCheck annotationInMethod = AnnotationUtils.findAnnotation(signature.getMethod(), PermissionCheck.class);
        // 优先取方法上的注解,若方法上无注解,则取类上的注解
        PermissionCheck annotation = annotationInMethod != null ? annotationInMethod : annotationInClass;
        if (annotation == null) {
            log.error("PermissionCheck annotation is null, {}", signature.toLongString());
            throw new RuntimeException("PermissionCheck annotation is null");
        }

        String authPoint = annotation.authPoint();
        if (permissionService.hasAuthPoint(authPoint)) { // 进行权限校验
            return joinPoint.proceed();
        } else {
            log.warn("user [{}] no permission, authPoint: {}", SessionUtils.getCurrentUser().getFullName(), authPoint);
            throw new RuntimeException("no permission: [" + authPoint + "]");
        }
    }
}

PermissionService的hasAuthPoint方法用于判断当前用户是否拥有所需权限点。

例如,将用户的拥有的权限点集合存储到Session中,校验时通过Session拿到用户的权限点集合进行判断

3. 用法示例

java 复制代码
package com.guo.demo.examples.permissioncheck;

import com.guo.demo.pojo.vo.Response;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;

@RestController
@RequestMapping("employee")
// 如果在类上使用注解,则对该类下所有public方法生效
// @PermissionCheck(authPoint = AuthPointConstant.EMPLOYEE_MANAGE)
public class EmployeeController {
    @Resource
    private EmployeeService employeeService;

    @PermissionCheck(authPoint = AuthPointConstant.ADD_EMPLOYEE) // 在方法上使用校验注解
    @PostMapping("add")
    public Response<?> add(@RequestBody @Valid AddEmployeeRequest request) {
        employeeService.add(request);
        return Response.success();
    }
}

AuthPointConstant是一个用于存放权限点常量的类,方便统一集中管理权限点。比如:

java 复制代码
public class AuthPointConstant {
    public static final String EMPLOYEE_MANAGE = "employee:manage"; // 管理员工
    public static final String ADD_EMPLOYEE = "employee:add"; // 添加员工
}

A. 参考文章

相关推荐
懒惰蜗牛20 分钟前
Day27 | Java集合框架之List接口详解
java·后端·java-ee·list
nsjqj23 分钟前
数据结构:Map 和 Set (二)
java·开发语言·数据结构
迎風吹頭髮29 分钟前
UNIX下C语言编程与实践18-UNIX 文件存储原理:目录、i 节点、数据块协同存储文件的过程
java·c语言·unix
nlog3n1 小时前
分布式排行榜系统设计方案
java·分布式
EnCi Zheng1 小时前
Java_钻石操作符详解
java·开发语言
Ytadpole1 小时前
性能革命的底层逻辑:深入理解 Spring Cloud Gateway 的 Reactor 核心
java·spring·gateway·reactor·响应式编程·cloud
Vahala0623-孔勇2 小时前
微服务网关深度设计:从Spring Cloud Gateway到Envoy,流量治理与安全认证实战指南
java·安全·微服务·云原生
拾忆,想起2 小时前
RabbitMQ事务机制深度剖析:消息零丢失的终极武器
java·开发语言·分布式·后端·rabbitmq·ruby
李贺梖梖2 小时前
DAY22 XML、XML解析
java