Springboot-AOP-权限管理功能

权限管理-AOP

近期回顾项目时决定将AOP权限管理这块整理一下:

什么是AOP/为什么要使用AOP?

AOP是软件设计领域中的面向切面编程 ,在 OOP 中, 我们以类(class)作为我们的基本单元, 而 AOP 中的基本单元是 Aspect(切面) **
够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于
减少系统的重复代码**,降低模块间的耦合度,并有利于未来的可拓展性和可维护性

AOP主要结构

简单地去理解,其实AOP要做三类事:

  • Pointcut 在哪里切入,也就是权限校验等非业务操作在哪些业务代码中执行。
  • Advice 在什么时候切入,是业务代码执行前还是执行后。
  • Advice 切入后做什么事,比如做权限校验、日志记录等。
  • AOP框架-来自知乎@终端研发部

可以看到处理时机是由 通知(Advice)类型来决定,而具体处理逻辑是写在了Aspect切面类中

元注解

这里使用元注解主要是为了进行各模块权限分配**@Permission**
@Target注解用于定义注解的使用位置
@Retention注解用于指明修饰的注解的生存周期,即会保留到哪个阶段
@Documented 指明修饰的注解
image.png

代码实现

1、首先引入依赖

<!--aop切面的使用-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--切面注解支持-->
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
</dependency>

2、定义aspect切面类**@Aspect**

创建一个AOP切面类,只要在类上加个@Aspect注解即可。@Aspect注解用来描述一个切面类,定义切面类的时候需要打上这个注解。@Component注解将该类交给 Spring 来管理。在这个类里实现advice:

/**
     * 定义切点(切入位置)
     * Pointcut后定义哪些bean哪些方法是需要处理的目标
     * *.* 代表controller包下所有类和所有方法
     * execution(修饰符表达式? 返回值表达式 类路径表达式?方法名表达式(参数表达式)异常表达式?)
     * 说明:包名部分的..表示当前包及其所有子包.后面带有?的表示为可选项.参数部分的..表示零个或多个任意参数
     */
@Pointcut("execution(public * cn.stu.scu.controller.*.*(..))")
public void privilege() {
    
    
    //        System.out.println("==>切入");//不执行
}

/**
     * 下面是核心业务
     * 权限环绕通知
     * joinPoint连接点
     */
@ResponseBody
@Around("privilege()") //value=privilege(),对应切点方法
//    @Around("execution(public * com.example.demo.controller.*.*(..))") //或者直接写入切入位置
//    @Around("execution(* com.example.demo.controller.*.*(..))") //修饰符默认就是public
public Object isAccessMethod(ProceedingJoinPoint joinPoint) throws Throwable {
    
    
    //增强处理
    MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();//获取访问的目标方法签名
    Method targetMethod = methodSignature.getMethod(); //目标方法

    //如果该方法上没有权限注解,直接调用目标方法
    if (!targetMethod.isAnnotationPresent(Permission.class)) {
    
    
        return joinPoint.proceed();//放行,调用目标组件方法
    } else {
    
    
        // 获取自定义注解对象
        Permission permission = targetMethod.getAnnotation(Permission.class);
        // 根据对象获取注解值
        int authorities = permission.authorities();

        Object[] args = joinPoint.getArgs();//获取目标方法的参数列表(用户名)
        if (args == null) {
    
    
            throw new RejectedExecutionException("参数错误");
        }
        String token = ((HttpServletRequest) args[0]).getHeader("X-Token");
        String currentUser = token;
        // 权限比对
        int nowPermission = userService.getPermission(currentUser);
        if (nowPermission >= 3) {
    
    
            throw new SecurityException("请重新登录");
            //                return "sorry,您不是管理员";
        } else if (nowPermission > authorities) {
    
    
            throw new RejectedExecutionException("权限错误");
            //                return "sorry,您不是管理员";
        } else {
    
    
            //                logger.info("您是管理员");
            return joinPoint.proceed();//放行
        }
    }
}

3、自定义注解@Permission

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Permission {
    
    

    //    String authorities() default "ADMIN";
    int authorities() default 3; //0开发者,1管理员,2普通用户

}

这里permission 在user数据表中有事先定义


下面梳理一下涉及到的各个知识点

AOP底层原理

拦截器与AOP区别

多个AOP执行顺序

@Permission-自定义注解

创建注解类,注意这是一个**@interface,在Kind出选择Annotation**
@Target({ElementType.TYPE}) 注解
ElementType 这个枚举类型的常量提供了一个简单的分类:注解可能出现在Java程序中的语法位置(这些常量与元注解类型(@Target)一起指定在何处写入注解的合法位置)
@Retention({RetentionPolicy.Runtime}) 注解
RetentionPolicy这个枚举类型的常量描述保留注解的各种策略,它们与元注解(@Retention)一起指定注释要保留多长时间

@Pointcut 注解,

用来定义一个切点,即上文中所关注的某件事情的入口,切入点定义了事件触发时机和定义需要拦截的东西。execution表达式:
以 execution(* * com.mutest.controller….(…))) 表达式为例:

  • 第一个 * 号的位置:表示返回值类型,* 表示所有类型。
  • 包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,在本例中指 com.mutest.controller包、子包下所有类的方法。
  • 第二个 * 号的位置:表示类名,* 表示所有类。
  • (…):这个星号表示方法名, 表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。

当定义一个Around增强处理方法时,该方法的第一个形参必须是ProceedingJoinPoint类型(至少一个形参)。

欢迎指教与交流

猜你喜欢

转载自blog.csdn.net/weixin_54594861/article/details/130021254