创建SpringBoot项目在我们做项目的时候可能会遇到这样的场景:给用户分配不同的角色,然后不同的角色对某一个方法有不同的权限,有些角色可以访问该方法,有的不能访问。这时候我们可以利用aop实现权限验证。
实现思路就是首先自定义一个注解,在方法上添加该注解,跟据注解的值来判断能否访问该方法。
数据准备导入依赖
1.8 UTF-8 UTF-8 2.3.7.RELEASE 2.5 1.3.3 4.1.2 aopalliance aopalliance1.0 org.springframework spring-aspects5.0.2.RELEASE org.aspectj aspectjweaver1.8.3 org.springframework spring-context5.0.2.RELEASE commons-logging commons-logging1.2 org.springframework spring-test5.0.2.RELEASE log4j log4j1.2.12 junit junit4.12 test org.apache.poi poi-ooxml4.1.2 commons-io commons-io${commons.io.version} commons-fileupload commons-fileupload${commons.fileupload.version} org.springframework.boot spring-boot-starter-freemarkerorg.springframework.boot spring-boot-starter-jdbcorg.springframework.boot spring-boot-starter-thymeleaforg.springframework.boot spring-boot-starter-webcom.alibaba fastjson1.2.72 com.baomidou mybatis-plus-boot-starter3.4.2 org.mybatis.spring.boot mybatis-spring-boot-starter2.1.4 org.springframework.boot spring-boot-devtoolsruntime true mysql mysql-connector-javaruntime org.projectlombok lomboktrue org.springframework.boot spring-boot-starter-testtest org.junit.vintage junit-vintage-engineorg.springframework.boot spring-boot-starter-logging* *test ch.qos.logback logback-classic配置application.yml
mybatis: mapper-locations: classpath:/mybatis*.xml type-aliases-package: com.example.note.domain map-underscore-to-camel-case: true mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl typeAliasesPackage: com.example.note.domain #存放实体类的目录路径 mapperLocations: classpath:mybatis*.xml # 全局配置id自增 => global-config: db-config: id-type: auto server: port: 8088 spring: application: name: note-back datasource: driver-class-name: com.mysql.cj.jdbc.Driver name: defaultDataSource password: '123456789' url: jdbc:mysql://localhost:3306/note?serverTimezone=UTC username: 'root'
AOP实现权限验证自定义注解
package com.example.noteback.permission.anno; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; //目标是方法(在方法上添加该注解) @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Permissions { public String value(); }创建controller类,定义两个方法
package com.example.noteback.permission.controller; import com.example.noteback.permission.anno.Permissions; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("permissions") public class PermissionsController { @Permissions(value = "/permissions/getUser") @GetMapping("/getUser") public String getUser(){ return "User"; } @Permissions(value = "/permissions/getAGi") @GetMapping("/getAGi") public String getAGi(){ return "AGi"; } }
测试创建PermissionsValidation类(类名自定义)
import com.example.noteback.permission.anno.Permissions; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; @Aspect @Component public class PermissionsValidation { //切入点 @Pointcut("@annotation(com.example.noteback.permission.anno.Permissions)") public void permissionsPoint() { } @Around("permissionsPoint()") public Object hasPermissions(ProceedingJoinPoint joinPoint) throws Throwable { } }定义切入点,放到上面的PermissionsValidation类里面
//切入点 @Pointcut("@annotation(com.example.noteback.permission.anno.Permissions)") public void permissionsPoint() { }使用环绕通知@Around实现权限验证,放到上面的PermissionsValidation类里面
//通过方法名获取切入点 @Around("permissionsPoint()") public Object hasPermissions(ProceedingJoinPoint joinPoint) throws Throwable { //方法签名 MethodSignature methodSignature=(MethodSignature) joinPoint.getSignature(); //获取方法 Method aimMethod= methodSignature.getMethod(); //获取 @Permissions 的值 String permissions=aimMethod.getAnnotation(Permissions.class).value(); //权限集合 ListpermissionsList=new ArrayList<>(); permissionsList.add("/permissions/getUser"); //返回数据 Object proceed=null; //如果权限集合包含 @Permissions 的值 if(permissionsList.contains(permissions)){ //允许通过,表调用的方法可以往下运行 proceed=joinPoint.proceed(); }else { proceed="没有权限"; } return proceed; } 编写完毕
源码地址上面定义的权限集合只包含 "/permissions/getUser"
访问:http://127.0.0.1:8088/permissions/getUser
访问:http://127.0.0.1:8088/permissions/getAGi
源码地址:git@gitee.com:AGi_R/note.git
在命令框输入:git clone git@gitee.com:AGi_R/note.git 直接下载源码



