SpringBoot使用AOP实现统一角色权限校验

 更新时间:2023年07月24日 10:59:17   作者:天罡gg  
这篇文章主要介绍了SpringBoot如何使用AOP实现 统一角色权限校验,文中有详细的代码示例讲解和操作流程,具有一定的参考价值,需要的朋友可以参考下

一、引入AOP starter

在tg-book-common中引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

对于spring boot的starter,我在之前的文章中已经反复说明过多次,不做赘述!
本项目中已经使用中的starter如下:

  • spring-boot-starter-web
  • spring-boot-starter-logging
  • mybatis-spring-boot-starter
  • pagehelper-spring-boot-starter

二、创建切面@Aspect + 定义切点@Pointcut

@Aspect注解方式,它的概念像@Aspect、@Pointcut、@Before、@After、@Around等注解都是来自于 AspectJ,但是功能的实现是纯 Spring AOP 自己实现的,主要有两大核心

  • 定义[切入点]:使用 @Pointcut 切点表达式,你可以理解成类似于正则表达式的强大东东。(例如本文的@annotation方式)
  • 定义[切入时机] 和 [增强处理逻辑]:五种通知Advice注解 对[切入点]执行增强处理, 包括:@Before、@After、@AfterRunning、@AfterThrowing、@Around

以下使用@Aspect 定义一个切面类,使用@Pointcut定义一个切点,切点表达式使用@annotation方式,也就是注解的方式。

// @Aspect和@Component定义一个切面类,@Slf4j是之前讲过的日志注解
@Component
@Aspect
@Slf4j
public class RoleAspect {
	// 核心一:定义切点(使用@annotation方式)
    @Pointcut(value = "@annotation( org.tg.book.common.annotation.Role)")
    public void pointCut() {}
}

三、封装校验@Role角色权限的方法

本文的AOP是上文拦截器Interceptor的另一种实现方式,所以请将上文的AuthInterceptor中的如下代码注释:

然后把这段代码拿过来,封装成一个方法,放到RoleAspect 中如下:

/**
 * 将@Role与登录用户的角色对比,如果是管理员返回true
 **/
private boolean checkAdminRole(Role role)  {
    // 校验角色
    if (role != null) {
        // 走到这,说明方法上加了@Role
        boolean isAdmin = false;
        AuthContextInfo authInfo = AuthContextInfo.getAuthInfo();
        for (int roleId : role.roleIds()) {
            if (authInfo.getRoleId().equals(roleId)) {
                isAdmin = true;
                break;
            }
        }
        if (!isAdmin) {
            log.info("[403]无权限, authInfo={}", authInfo);
            return false;
        }
    }
    return true;
}

方法逻辑很简单:将@Role与登录用户的角色对比,如果是管理员返回true,否则返回false

四、AOP两种实现方式

4.1 前置通知@Before方式

因为角色权限校验代码,发生于【业务方法代码】之前,所以可以使用前置通知@Before方式,代码如下:

@Before("pointCut()")
public void before(JoinPoint joinPoint) throws NoSuchMethodException {
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Class<?> clazz = joinPoint.getTarget().getClass();
    Method method = clazz.getMethod(signature.getName(), signature.getParameterTypes());
    Role role = method.getAnnotation(Role.class);
    boolean isAdminRole = checkAdminRole(role);
    if (!isAdminRole) {
        throw new RuntimeException("无权限");
    }
}

核心逻辑是获得@Role注解,然后进行校验,如果非管理员,则抛出异常。这里实现的比较简单,当后面我们实现了【全局异常处理】以后,这里就可以换成自定义的异常类,交给【全局异常处理】统一处理!

4.2 环绕通知@Around方式

如果不抛出异常的话,如何处理?

可以使用@Around方式,环绕通知@Around可以控制在【业务方法代码】之前校验,并且可以返回结果,所以我们就不需要抛出异常了!

@Around("pointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    Class<?> clazz = joinPoint.getTarget().getClass();
    Method method = clazz.getMethod(signature.getName(), signature.getParameterTypes());
    Role role = method.getAnnotation(Role.class);
    boolean isAdminRole = checkAdminRole(role);
    if (!isAdminRole) {
        return TgResult.fail("403", "无权限");
    }
    return joinPoint.proceed();
}

获取Role 之前的代码都是一模一样的,区别就是这里没有抛出异常,而是返回统一结果TgResult,这也正是封装统一返回结果的好处之一!!!

特别注意: before和around是两种实现方式,所以不必在意从joinPoint得到role的重复代码,因为最终只会写一份代码,对于before和around我更建议使用around的方式!

以上就是SpringBoot使用AOP实现统一角色权限校验的详细内容,更多关于SpringBoot AOP统一角色权限校验的资料请关注脚本之家其它相关文章!

相关文章

  • 详解JVM中的GC调优

    详解JVM中的GC调优

    我们经常会听到甚至需要自己动手去做GC调优。那么GC调优的目的到底是什么呢?让程序跑得更快?让GC消耗更少的资源?还是让程序更加稳定?带着这些疑问来读一下这篇文章,将会得到一个系统的甚至是不一样的结果。
    2021-06-06
  • java枚举如何使用spring的@value注入属性

    java枚举如何使用spring的@value注入属性

    这篇文章主要介绍了java枚举如何使用spring的@value注入属性问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • SpringBoot拦截器实现登录拦截的示例代码

    SpringBoot拦截器实现登录拦截的示例代码

    本文主要介绍了SpringBoot拦截器实现登录拦截,文中根据实例编码详细介绍的十分详尽,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Java实现动态规划背包问题

    Java实现动态规划背包问题

    本文主要介绍使用java实现动态规划的背包问题,详细使用图文和多种案例进行解析,帮助理解该算法
    2021-06-06
  • SpringBoot之RabbitMQ的使用方法

    SpringBoot之RabbitMQ的使用方法

    这篇文章主要介绍了SpringBoot之RabbitMQ的使用方法,详细的介绍了2种模式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-12-12
  • 关于Spring多数据源TransactionManager冲突的解决方案

    关于Spring多数据源TransactionManager冲突的解决方案

    这篇文章主要介绍了关于Spring多数据源TransactionManager冲突的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Spring Boot如何使用JDBC获取相关的数据详解

    Spring Boot如何使用JDBC获取相关的数据详解

    这篇文章主要给大家介绍了关于Spring Boot如何使用JDBC获取相关数据的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • SpringBoot中的@EnableConfigurationProperties注解原理及用法

    SpringBoot中的@EnableConfigurationProperties注解原理及用法

    在SpringBoot中,@EnableConfigurationProperties注解是一个非常有用的注解,它可以用于启用对特定配置类的支持,在本文中,我们将深入探讨@EnableConfigurationProperties注解,包括它的原理和如何使用,需要的朋友可以参考下
    2023-06-06
  • springboot引入远程nacos配置文件错误的解决方案

    springboot引入远程nacos配置文件错误的解决方案

    本文为解决Spring Cloud Alibaba中配置导入问题,提供了详细的步骤说明,包括引入依赖、配置nacos、创建bootstrap.yml文件以及测试配置导入是否成功的方法,帮助开发者快速解决相关问题
    2024-09-09
  • Java 基础语法让你弄懂类和对象

    Java 基础语法让你弄懂类和对象

    C 语言是面向过程的,而 Java 是面向对象是我们常听到的一句话,这章将带你揭晓Java 基础语法中类与对象到底是什么,需要的朋友请参考下文
    2021-08-08

最新评论