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统一角色权限校验的资料请关注脚本之家其它相关文章!

相关文章

  • SpringBoot如何实现starter原理详解

    SpringBoot如何实现starter原理详解

    这篇文章主要介绍了SpringBoot如何实现starter原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • Java注解Annotation解析

    Java注解Annotation解析

    这篇文章主要为大家详细介绍了Java注解Annotation,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • Java中的注解、元注解详细解析

    Java中的注解、元注解详细解析

    这篇文章主要介绍了Java中的注解、元注解详细解析,注解也叫元数据,与类、接口、枚举是在同一个层次,它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释,需要的朋友可以参考下
    2023-11-11
  • Java面试重点中的重点之Elasticsearch核心原理

    Java面试重点中的重点之Elasticsearch核心原理

    ElasticSearch是一个基于Lucene的搜索引擎,是用Java语言开发的,能够达到实时搜索,稳定,可靠,快速,安装使用方便,作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎,是最受欢迎的企业搜索引擎
    2022-01-01
  • elasticsearch索引创建create index集群matedata更新

    elasticsearch索引创建create index集群matedata更新

    这篇文章主要介绍了elasticsearch索引创建create index及集群matedata更新,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • springboot集成Mybatis的详细教程

    springboot集成Mybatis的详细教程

    今天给大家带来的还是关于springboot的相关知识,文章围绕着springboot集成Mybatis的详细教程展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • IntelliJ IDEA Java项目手动添加依赖 jar 包的方法(图解)

    IntelliJ IDEA Java项目手动添加依赖 jar 包的方法(图解)

    这篇文章主要介绍了IntelliJ IDEA Java项目手动添加依赖 jar 包,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • Java Map集合与Collection类的使用详解

    Java Map集合与Collection类的使用详解

    这篇文章主要介绍了Java Map集合的使用及Collection工具类使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-11-11
  • 用JAVA实现杨辉三角实例

    用JAVA实现杨辉三角实例

    大家好,本篇文章主要讲的是用JAVA实现杨辉三角实例,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • 零基础如何系统的学习Java

    零基础如何系统的学习Java

    这篇文章主要介绍了零基础如何系统的学习Java,很多朋友纠结这个问题,教材书不知道从何学起,今天小编给大家分享一篇教程帮助到家梳理这方面的知识
    2020-07-07

最新评论