通过AOP 实现权限登录拦截 springboot+mybatis-plus
需求:公司为了实现拦截未登录的用户直接请求接口,要求Java与前端都要做出安全拦截
设计:想通过spring的AOP方式实现,于是去网上查看了相关资料
参考:可参考博客
第一步:公司项目没有用过AOP需要引入相关的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
实现方式有两种,一种是通过自定义注解的方式,一种是通过@Pointcut切点的方式实现,对我来说Java对外的接口基本都要拦截,注解的方式并不适合我,于是选择了切点的方式拦截自定义的controller类即可,下面两种都可以简单的记录下,以供参考
通过@Pointcut切点的方式实现
创建一个切面类PermissionAspect并引入相关注解
@Aspect //表示这是一个切面
@Component //交给springboot管理
//@ResponseBody
public class PermissionAspect {}
定义一个切点,表示需要对哪些类生效,我这里暂时是想拦截所有的控制层的代码,加上对用的不是很熟练下这样将就着用吧
/**
* 定义切点,这是一个标记方法
*/
@Pointcut("execution(* com.danganku.file.controller.*Controller.*(..))")
//@Pointcut("execution( * com.danganku.file.controller.UpdateController.*(..)))")
public void pointCunt(){}
定义一个前置方法的注解,我是想在程序执行前就执行我的拦截方法
你可以根据需求选择前置方法后置方法或者环绕哦
AspectJ支持的5种类型的通知注解:
@Before:前置通知,在方法执行之前执行
@After:后置通知,在方法执行之后执行
@AfterRunning:返回通知,在方法返回结果后执行
@AfterThrowing:异常通知,在方法抛出异常之后执行
@Around:环绕通知,围绕着方法执行
@Before("pointCunt()" )//pointCunt():上面代码的定义的方法,可以自己定义
public void Before(JoinPoint joinPoint){
//try {
// logger.info("---前置通知---");
//
// // 获取目标方法的参数信息
// logger.info("目标对象参数信息: {}", Arrays.toString(joinPoint.getArgs()));
//
// // AOP代理类的信息
// logger.info("AOP代理类: {}", joinPoint.getThis());
//
// // 代理的目标对象
// logger.info("代理的目标对象: {}", joinPoint.getTarget());
//
// // 通知的签名
// Signature signature = joinPoint.getSignature();
// // 代理的是哪一个方法
// logger.info("代理的方法名: {}", signature.getName());
//
// // AOP代理类的名字
// logger.info("AOP代理类的名字: {}", signature.getDeclaringTypeName());
//
// // AOP代理类的类信息
// logger.info("AOP代理类的类信息: {}", signature.getDeclaringType());
/**
*你的逻辑代码
*/
System.out.println("通过权限验证");
}
到此切点方式基本就结束了,博主也是第一次用,记录一下,加深印象,有问题也可以联系我
下面看下使用的注解的方式
第一步:定义一个注解类Permission
@Target({ElementType.TYPE,ElementType.METHOD} )
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Permission {
}
@Target:
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention(注解的生命周期):
1、RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
2、RetentionPolicy.CLASS:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期;
3、RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
@Documented:用于描述其他类型的annotation应该作为标记的程序成员的公共应用编程接口
如果要注解生效的话可以看下图,类的标识符号是变了的哦,会有一个绿色的@符号
第二步:定义一个前置方法,然后实现我们的业务代码
@Before( value = "@annotation(permission)")
public Result userPermission( JoinPoint joinpoint,Permission permission) throws Exception {
System.out.println("权限验证");
//1.获取请求参数
Object[] objects = joinpoint.getArgs();
for(Object obj : objects){
if (obj instanceof Sessions){
String sessionById = sessionService.findSessionById(((Sessions) obj).getPHPSESSID().toString());
//若校验失败,抛出自定义异常
if (StringUtils.isBlank(sessionById)){
System.out.println( "抱歉,您无该操作权限" );
throw new CustomException(ExceptionEnum.USER_PERMISSION);
}
}
}
return ResultUtil.ResultSuccess("","");
}
最后一步,再对应的方法引入注解
注解方式也到此结束了,博主也是第一次使用了,测试过没有问题,可以参考下哦