返回

揭秘 Spring Boot 中 AOP 切面的权限校验魔法

后端

理解 AOP

在深入探讨 AOP 权限校验之前,我们先来了解一下 AOP 的基本概念和原理。

什么是 AOP

AOP,全称 Aspect-Oriented Programming,即面向切面编程,是一种编程范式,它允许我们以一种非侵入的方式为应用程序添加功能。传统的编程方式是将功能直接嵌入到应用程序代码中,而 AOP 则允许我们将功能分离出来,并以一种模块化的方式添加到应用程序中。

AOP 体系与概念

AOP 体系主要包括以下几个概念:

  • 切面 (Aspect) :切面是 AOP 的核心概念,它封装了与某个特定功能相关的代码。
  • 连接点 (Join Point) :连接点是指程序执行过程中的特定点,例如方法调用、字段访问等。
  • 通知 (Advice) :通知是指在连接点执行时执行的代码。
  • 切入点 (Pointcut) :切入点是用于指定通知将在哪些连接点执行的表达式。

AOP 实例

为了更好地理解 AOP,我们来看两个简单的实例。

第一个实例

@Aspect
public class LoggingAspect {

    @Before("execution(* com.example.demo.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint.getSignature().getName());
    }

    @After("execution(* com.example.demo.service.*.*(..))")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("After method: " + joinPoint.getSignature().getName());
    }
}

在这个实例中,我们定义了一个名为 LoggingAspect 的切面,它包含了两个通知:logBefore()logAfter()logBefore() 通知将在任何以 com.example.demo.service 包开头的类中的任何方法调用之前执行,而 logAfter() 通知将在这些方法调用之后执行。

第二个实例

@Aspect
public class SecurityAspect {

    @Pointcut("execution(* com.example.demo.controller.*.*(..))")
    public void securityPointcut() {}

    @Around("securityPointcut()")
    public Object securityAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        // 检查用户是否具有访问该方法的权限

        // 如果用户具有权限,则执行该方法
        return joinPoint.proceed();

        // 如果用户没有权限,则抛出异常
        throw new UnauthorizedException();
    }
}

在这个实例中,我们定义了一个名为 SecurityAspect 的切面,它包含了一个切入点 securityPointcut() 和一个通知 securityAdvice()securityPointcut() 切入点指定了通知将在哪些连接点执行,而 securityAdvice() 通知将在这些连接点执行。在 securityAdvice() 通知中,我们首先检查用户是否具有访问该方法的权限,如果用户具有权限,则执行该方法,否则抛出异常。

AOP 相关注解

在 Spring Boot 中,我们可以使用 AOP 相关注解来实现权限校验。这些注解包括:

  • @Pointcut:用于指定通知将在哪些连接点执行。
  • @Around:用于在连接点周围执行通知。
  • @Before:用于在连接点之前执行通知。
  • @After:用于在连接点之后执行通知。
  • @AfterReturning:用于在连接点正常返回后执行通知。

@Pointcut

@Pointcut 注解用于指定通知将在哪些连接点执行。例如:

@Pointcut("execution(* com.example.demo.controller.*.*(..))")
public void securityPointcut() {}

这个切入点指定了通知将在以 com.example.demo.controller 包开头的类中的任何方法调用之前执行。

@Around

@Around 注解用于在连接点周围执行通知。例如:

@Around("securityPointcut()")
public Object securityAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
    // 检查用户是否具有访问该方法的权限

    // 如果用户具有权限,则执行该方法
    return joinPoint.proceed();

    // 如果用户没有权限,则抛出异常
    throw new UnauthorizedException();
}

这个通知将在 securityPointcut() 切入点指定的连接点周围执行。在通知中,我们首先检查用户是否具有访问该方法的权限,如果用户具有权限,则执行该方法,否则抛出异常。

@Before

@Before 注解用于在连接点之前执行通知。例如:

@Before("execution(* com.example.demo.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
    System.out.println("Before method: " + joinPoint.getSignature().getName());
}

这个通知将在以 com.example.demo.service 包开头的类中的任何方法调用之前执行。在通知中,我们将输出方法名。

@After

@After 注解用于在连接点之后执行通知。例如:

@After("execution(* com.example.demo.service.*.*(..))")
public void logAfter(JoinPoint joinPoint) {
    System.out.println("After method: " + joinPoint.getSignature().getName());
}

这个通知将在以 com.example.demo.service 包开头的类中的任何方法调用之后执行。在通知中,我们将输出方法名。

@AfterReturning

@AfterReturning 注解用于在连接点正常返回后执行通知。例如:

@AfterReturning(pointcut = "execution(* com.example.demo.service.*.*(..))", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
    System.out.println("After method: " + joinPoint.getSignature().getName() + ", result: " + result);
}

这个通知将在以 com.example.demo.service 包开头的类中的任何方法调用正常返回后执行。在通知中,我们将输出方法名和返回结果。

总结

在本文中,我们介绍了 Spring Boot 中 AOP 切面的权限校验技巧。我们首先了解了 AOP 的基本概念和原理,然后通过实例演示了如何实现权限校验,最后还全面解析了相关注解。希望本文能够帮助您更好地理解和使用 AOP 切面来实现权限校验。