使用AOP+自定义注解完成spring boot的接口权限校验
记使用AOP+自定义注解完成接口的权限校验,代码如下:
pom文件添加所需依赖:
1 <dependency> 2 <groupId>org.aspectj</groupId> 3 <artifactId>aspectjrt</artifactId> 4 <version>1.8.9</version> 5 </dependency> 6 <dependency> 7 <groupId>org.springframework.boot</groupId> 8 <artifactId>spring-boot-starter-aop</artifactId> 9 </dependency>
先自定义注解@MyAnnotation,注解中可以设置所需参数:
1 package com.itcq.aop; 2 3 import java.lang.annotation.*; 4 5 //定义注解可以使用的范围 6 @Target({ElementType.TYPE, ElementType.METHOD}) 7 @Retention(RetentionPolicy.RUNTIME) 8 @Documented 9 public @interface MyAnnotation { 10 11 String name(); 12 }
定义解析注解的MyAnnotationService,完成接口权限校验的逻辑,这里我是获取接口请求时header中的user_name参数,进行校验:
1 package com.itcq.aop; 2 3 import lombok.extern.slf4j.Slf4j; 4 import org.aspectj.lang.ProceedingJoinPoint; 5 import org.aspectj.lang.Signature; 6 import org.aspectj.lang.annotation.Around; 7 import org.aspectj.lang.annotation.Aspect; 8 import org.aspectj.lang.annotation.Pointcut; 9 import org.springframework.stereotype.Component; 10 import org.springframework.web.context.request.RequestContextHolder; 11 import org.springframework.web.context.request.ServletRequestAttributes; 12 13 import javax.servlet.http.HttpServletRequest; 14 15 @Aspect 16 @Component 17 @Slf4j 18 public class MyAnnotationService { 19 20 //切入点表达式决定了用注解方式的方法切还是针对某个路径下的所有类和方法进行切,方法必须是返回void类型 21 @Pointcut("@annotation(com.itcq.aop.MyAnnotation)") 22 private void roleCheckCut() {}; 23 24 //定义了切面的处理逻辑。即方法上加了@MyAnnotation注解,将会进行权限校验 25 @Around("roleCheckCut()") 26 public Object operateAuth(ProceedingJoinPoint pjp) throws Throwable { 27 28 //打印日志 29 Signature signature = pjp.getSignature(); 30 String className = pjp.getTarget().getClass().getSimpleName(); 31 String methodName = signature.getName(); 32 log.info("className:{},methodName:{}", className, methodName); 33 34 //获取接口请求时header中的user_name参数,进行校验 35 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 36 String userName = request.getHeader("user_name"); 37 //这里可以Apollo配置可以放行的角色 38 if (!"hwy".equals(userName)) { 39 throw new Exception(userName+"权限校验不通过"); 40 } 41 return pjp.proceed(); 42 } 43 }
最后在controller层中编写测试方法,利用postman测试接口:
1 package com.itcq.controller; 2 3 import com.itcq.aop.MyAnnotation; 4 import com.itcq.service.TestService; 5 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.web.bind.annotation.GetMapping; 7 import org.springframework.web.bind.annotation.RequestHeader; 8 import org.springframework.web.bind.annotation.RequestParam; 9 import org.springframework.web.bind.annotation.RestController; 10 11 @RestController 12 public class TestController { 13 14 @Autowired 15 private TestService testService; 16 17 @GetMapping("/test") 18 @MyAnnotation(name = "HWY") 19 public String testMethod(@RequestHeader(name = "user_name") String userName, 20 @RequestParam(name = "user_age") Integer userAge) { 21 22 return testService.testMethod(userName, userAge); 23 } 24 }
两种不同请求参数的测试结果如下:
参数正确时的返回结果:
参数不正确时的返回结果,接口报错,控制台输出:
可以发现使用AOP+自定义注解的形式完成了接口的权限校验,当然这只算是比较初级的应用,AOP+自定义注解还有很大的探索空间。