Spring AOP实现权限检查的功能

前言

最近开发了一个接口,完成后准备自测时,却被拦截器拦截了,提示:(AUTH-NO)未能获得有效的请求参数!怎么会这样呢?

于是我全局搜了这个提示语,结果发现它被出现在一个Aspect类当中了,并且把一个 @interface 作为了一个切点,原来这里利用了Spring AOP面向切面的方式进行权限控制。

正文

Spring AOP 即面向切面,是对OOP面向对象的一种延伸。
AOP机制可以让开发者把业务流程中的通用功能抽取出来,单独编写功能代码。在业务流程执行过程中,Spring框架会根据业务流程要求,自动把独立编写的功能代码切入到流程的合适位置。

我们通过AOP机制可以实现:Authentication 权限检查、Caching 缓存、Context passing 内容传递、Error handling 错误处理等功能,这里我们讲一下怎么用Spring AOP来实现权限检查。

Spring AOP实现权限检查

引入依赖

<!--lombok-->
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.18.2</version>
  <optional>true</optional>
</dependency>

<!--Spring AOP-->
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-aop</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-aspects</artifactId>
</dependency>

<dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjweaver</artifactId>
 <version>1.9.2</version>
</dependency>

<dependency>
 <groupId>aopalliance</groupId>
 <artifactId>aopalliance</artifactId>
 <version>1.0</version>
</dependency>

MyPermissionTag.class自定义注解

  • @Retention: 用来修饰注解,是注解的注解,称为元注解。
  • @Target:用来说明对象的作用范围
/**
 * 用户请求权限校验
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyPermissionTag {
  String value() default "";
  String name() default "";
}

这里特别讲一下@Retention,按生命周期来划分可分为3类:

  • RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃(运行时去动态获取注解信息);
  • RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期(在编译时进行一些预处理操作);
  • RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在(做一些检查性的操作);

这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码。

AuthInterceptor 权限检查的切面

这里简单介绍一下,切面的执行方法和其执行顺序:

  • @Around 通知方法将目标方法封装起来
  • @Before 通知方法会在目标方法调用之前执行
  • @After 通知方法会在目标方法返回或者异常后执行
  • @AfterReturning 通知方法会在目标方法返回时执行
  • @Afterthrowing 通知方法会在目标方法抛出异常时执行

这里以一个返回正常的情况为例:(异常替换最后一步即可)

AuthInterceptor.class

注意要在启动类扫描这个class,并且添加 @EnableAspectJAutoProxy(proxyTargetClass =
true)

@Slf4j
@Aspect
@Component
public class AuthInterceptor {

  /**
   * 参数处理
   *
   * @param point
   */
  @Before("@annotation(com.luo.common.tag.MyPermissionTag)")
  public void beforeProReq(JoinPoint point) {
    log.info("前置拦截-开始");
    Request req = getOperationRequest(point.getArgs());
    if (req != null) {
      //解密帐号
      log.info("前置拦截-开始解密ACCOUNT:{}", req.getAccount());

      log.info("前置拦截-结束解密ACCOUNT:{}", req.getAccount());
    }
    log.info("前置拦截-结束");
  }

  @Around("@annotation(com.luo.common.tag.MyPermissionTag)")
  public Object authCheck(ProceedingJoinPoint pjp) throws Throwable {
    log.info("权限拦截-开始");
    //请求方法
    ReqMethod reqMethod = getPermissionTag(pjp);

    MyPermissionTag myPermissionTag =reqMethod.perTag;
    log.info(myPermissionTag.value()); //获取配置的值
    log.info("权限拦截-开始-拦截到方法:{}", reqMethod.getMethodName());

    if("true".equals(myPermissionTag.value().toString())){
      //错误返回
      Response notGoRes = new Response();
      Request req = getOperationRequest(pjp.getArgs());
      // 校验请求对象
      if (req == null) {
        notGoRes.setErrorMsg("(AUTH)未能获得有效的请求参数!");
        log.info("(AUTH-NO)未能获得有效的请求参数!");
        return notGoRes;
      }else {//可以在这里根据请求参数对请求做进一步校验

        log.info("完成请求校验:"+req);

      }
    }else {
      log.info("未开启权限校验");
    }

    return pjp.proceed();
  }

  /**
   * 获取 request 接口中的请求参数
   * @param args
   * @return
   */
  private Request getOperationRequest(Object[] args) {
    if (args == null || args.length <= 0) {
      log.error("AUTH权限验证:拦截方法的请求参数为空!");
      return null;
    }
    Object obj = args[0];
    if (obj instanceof Request) {
      log.info("AUTH权限验证:请求对象为正确的OperationRequest对象");
      return (Request) obj;
    }
    return null;
  }

  /**
   * 获取拦截的资源标签
   * 这里可以获取方法名+注解信息(包括 key+value 等)
   * @param pjp
   * @return
   * @throws SecurityException
   * @throws NoSuchMethodException
   */
  private ReqMethod getPermissionTag(ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
    Signature signature = pjp.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
    Method targetMethod = methodSignature.getMethod();
    Method realMethod = pjp.getTarget().getClass().getDeclaredMethod(signature.getName(), targetMethod.getParameterTypes());
    MyPermissionTag permissionTag = realMethod.getAnnotation(MyPermissionTag.class);
    return new ReqMethod(permissionTag, realMethod.getName());
  }

  @Setter
  @Getter
  class ReqMethod {

    private MyPermissionTag perTag;
    private String methodName;

    public ReqMethod(MyPermissionTag perTag, String methodName) {
      this.perTag = perTag;
      this.methodName = methodName;
    }

  }
}

验证

测试接口

@PostMapping("/helloluo")
@MyPermissionTag(value = "true")
public String helloluo(UserPojoReq userPojoReq){
  return "Hello World";
}

发送请求

验证

到此这篇关于Spring AOP实现权限检查的功能的文章就介绍到这了,更多相关Spring AOP 权限检查内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • spring aop实现用户权限管理的示例

    AOP 在实际项目中运用的场景主要有 权限管理(Authority Management).事务管理(Transaction Management).安全管理(Security).日志管理(Logging)和调试管理(Debugging) 等. 问题源于项目开发 最近项目中需要做一个权限管理模块,按照之前同事的做法是在controller层的每个接口调用之前上做逻辑判断,这样做也没有不妥,但是代码重复率太高,而且是体力劳动,so,便有了如题所说的使用spring aop做一个切点来实现通用功能的

  • SpringBoot使用AOP+注解实现简单的权限验证的方法

    SpringAOP的介绍:传送门 demo介绍 主要通过自定义注解,使用SpringAOP的环绕通知拦截请求,判断该方法是否有自定义注解,然后判断该用户是否有该权限.这里做的比较简单,只有两个权限:一个普通用户.一个管理员. 项目搭建 这里是基于SpringBoot的,对于SpringBoot项目的搭建就不说了.在项目中添加AOP的依赖:<!--more---> <!--AOP包--> <dependency> <groupId>org.springfram

  • Java之Spring AOP 实现用户权限验证

    每个项目都会有权限管理系统 无论你是一个简单的企业站,还是一个复杂到爆的平台级项目,都会涉及到用户登录.权限管理这些必不可少的业务逻辑.有人说,企业站需要什么权限管理阿?那行吧,你那可能叫静态页面,就算这样,但你肯定也会有后台管理及登录功能. 每个项目中都会有这些几乎一样的业务逻辑,我们能不能把他们做成通用的系统呢? AOP 实现用户权限验证 AOP 在实际项目中运用的场景主要有权限管理(Authority Management).事务管理(Transaction Management).安全管

  • Spring AOP实现功能权限校验功能的示例代码

    实现功能权限校验的功能有多种方法,其一使用拦截器拦截请求,其二是使用AOP抛异常. 首先用拦截器实现未登录时跳转到登录界面的功能.注意这里没有使用AOP切入,而是用拦截器拦截,因为AOP一般切入的是service层方法,而拦截器是拦截控制器层的请求,它本身也是一个处理器,可以直接中断请求的传递并返回视图,而AOP则不可以. 1.使用拦截器实现未登录时跳转到登录界面的功能 1.1 拦截器SecurityInterceptor package com.jykj.demo.filter; import

  • spring aop 拦截业务方法,实现权限控制示例

    难点:aop类是普通的java类,session是无法注入的,那么在有状态的系统中如何获取用户相关信息呢,session是必经之路啊,获取session就变的很重要.思索很久没有办法,后来在网上看到了解决办法. 思路是: i. SysContext  成员变量 request,session,response ii. Filter 目的是给 SysContext 中的成员赋值 iii.然后在AOP中使用这个SysContext的值 要用好,需要理解  ThreadLocal和  和Filter

  • Spring Boot 通过AOP和自定义注解实现权限控制的方法

    本文介绍了Spring Boot 通过AOP和自定义注解实现权限控制,分享给大家,具体如下: 源码:https://github.com/yulc-coding/java-note/tree/master/aop 思路 自定义权限注解 在需要验证的接口上加上注解,并设置具体权限值 数据库权限表中加入对应接口需要的权限 用户登录时,获取当前用户的所有权限列表放入Redis缓存中 定义AOP,将切入点设置为自定义的权限 AOP中获取接口注解的权限值,和Redis中的数据校验用户是否存在该权限,如果R

  • Spring AOP实现权限检查的功能

    前言 最近开发了一个接口,完成后准备自测时,却被拦截器拦截了,提示:(AUTH-NO)未能获得有效的请求参数!怎么会这样呢? 于是我全局搜了这个提示语,结果发现它被出现在一个Aspect类当中了,并且把一个 @interface 作为了一个切点,原来这里利用了Spring AOP面向切面的方式进行权限控制. 正文 Spring AOP 即面向切面,是对OOP面向对象的一种延伸. AOP机制可以让开发者把业务流程中的通用功能抽取出来,单独编写功能代码.在业务流程执行过程中,Spring框架会根据业

  • Spring AOP + 注解实现统一注解功能

    1. 概述 在一般系统中,当我们做了一些重要的操作时,如登陆系统,添加用户,删除用户等操作时,我们需要将这些行为持久化.本文我们通过Spring AOP和Java的自定义注解来实现日志的插入.此方案对原有业务入侵较低,实现较灵活 2. 日志的相关类定义 我们将日志抽象为以下两个类:功能模块和操作类型 使用枚举类定义功能模块类型ModuleType,如学生.用户模块 public enum ModuleType { DEFAULT("1"), // 默认值 STUDENT("2

  • 使用Spring AOP实现用户操作日志功能

    目录 我使用Spring AOP实现了用户操作日志功能 需求分析 功能实现 1. 需要一张记录日志的 Log 表 导出的 sql 如下: 2.我使用的是 Spring Boot 所以需要引入 spring aop 的 starter 3.Log 实体类 4.ILog 注解 5.切面类 LogAspect 总结 我使用Spring AOP实现了用户操作日志功能 今天答辩完了,复盘了一下系统,发现还是有一些东西值得拿出来和大家分享一下. 需求分析 系统需要对用户的操作进行记录,方便未来溯源 首先想到

  • Spring AOP统一功能处理示例代码

    目录 1. 什么是Spring AOP? 2. 为什要用 AOP? 3. Spring AOP 应该怎么学习呢? 3.1AOP组成 3.1.1 切面(Aspect) 3.1.2 连接点(Join Point) 3.1.3 切点(Pointcut) 3.1.4 通知(Advice) 3.2 Spring AOP实现 3.2.1 添加 AOP 框架支持 3.2.2 定义切面和切点. 3.2.3 定义相关通知 3.3 Spring AOP 实现原理 3.3.1 动态代理 3.3.2 JDK和CGLIB

  • Spring boot security权限管理集成cas单点登录功能的实现

    目录 1.Springboot集成Springsecurity 2.部署CASserver 3.配置CASclient 挣扎了两周,Spring security的cas终于搞出来了,废话不多说,开篇! 1.Spring boot集成Spring security 本篇是使用spring security集成cas,因此,先得集成spring security新建一个Spring boot项目,加入maven依赖,我这里是用的架构是Spring boot2.0.4+Spring mvc+Spri

  • 基于 Spring Aop 环绕通知实现 Redis 缓存双删功能(示例代码)

    基于 spring aop 常规应用场景多是用于日志记录以及实现 redis 分布式锁,在 github 中也有项目是把它拿来当作缓存的异常捕捉.从而避免影响实际业务的开发:在某天,笔者有个业务开发是给某个服务模块增加 redis 缓存.增加缓存就会涉及 redis 删除.所以笔者就在思考是不是可以用环绕通知的方式来进行实现 代码实现 结构示意图: 自定义注解 RedisDelByDbUpdate @Repeatable 表示允许在同一个地方上使用相同的注解,没有该注解时贴相同注解会报错 @Ta

  • Spring security实现权限管理示例

    Spring security实现权限管理示例,具体如下: 1.配置文件 1.POM.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.o

随机推荐