主要注解
@interface:继承了 Annotation 接口的自定义注解,定义注释类型。
@Target:表示这个注解可以应用的地方,此处做权限校验是用在方法上的,所以此处的值为 @Target(ElementType.METHOD)
@Retention:表示这个注解的保留策略,此处定义为 @Retention(RetentionPolicy.RUNTIME)
@Aspect:AOP依赖中的类,表示这个类是一个 Aspect,当应用程序中的其他组件和这个类中的方法相匹配时,spring 将自动执行这个方法,实现横切关注点的处理,此处横向关注点就是权限校验。
步骤
1. 引入依赖
引入 spring data starter AOP 依赖,版本对应项目的springboot 版本:Maven Repository: org.springframework.boot » spring-boot-starter-aop (mvnrepository.com)
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><version>2.7.2</version>
</dependency>
2. 编写 身份接口注解
这个注解的主要用途是用于身份验证,确保用户具有适当的权限来执行特定的操作。
/*** 用户权限接口* 包含用户角色* target注解表示该注解可以用于方法上* retention注解表示该注解在运行时有效*/@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {/*** 用户有的身份,只要有身份就是true**/String[] anyRoles() default "";/*** 用户必须有的身份,比如会员,管理员*/String mustRole() default "";}
3. 编写 AOP 切面类
/*** 权限校验拦截*/
@Aspect
@Component
public class AuthInterceptor {/*** 用户登录态键*/private String USER_LOGIN_STATE = "userLoginState";@Resourceprivate UserService userService;@Around("@annotation(authCheck)")public Object authCheck(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {//先获取当前用户登录态RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();//获取当前用户信息Object attribute = request.getSession().getAttribute(USER_LOGIN_STATE);User user=(User) attribute;if(user==null){return -1;}//获取用户权限String userRole = user.getUserRole();//获取用户角色列表String mustRole = authCheck.mustRole();List<String> anyRoles = Arrays.stream(authCheck.anyRoles()).filter(StringUtils::isNotBlank).collect(Collectors.toList());//判断当前用户权限是否在用户角色列表中if(CollectionUtils.isNotEmpty(anyRoles)){if (!anyRoles.contains(userRole)){System.out.println("当前用户为权限不足,无法访问该接口");return -1;}}//判断当前用户权限是否在必须权限中if(StringUtils.isNotBlank(mustRole)){if(!mustRole.equals(userRole)){System.out.println("当前用户为普通用户,无法访问该接口");return -1;}};//检验完毕,执行后续方法。跳出切面return joinPoint.proceed();}}
4.测试
在数据库直接添加一条数据
测试 mustRole 为 普通用户
在需要校验权限的接口添加注解。
@AuthCheck(mustRole = "user")@PostMapping("/test")public void test(String string ){System.out.println("holleworld:"+ string);}
当权限校验通过就会输出 helloworld,失败就输出校验失败。
使用 swagger API 文档进行测试
测试 mustRole 为管理员
@AuthCheck(mustRole = "admin")@PostMapping("/test")public void test(String string ){System.out.println("holleworld:"+ string);}
校验通过。
测试 anyRole 不包含
@AuthCheck(anyRoles = {"user","vip"})@PostMapping("/test")public void test(String string ){System.out.println("holleworld:"+ string);}
}
校验不通过。
测试 anyRole 包含
@AuthCheck(anyRoles = {"user","vip","admin"})@PostMapping("/test")public void test(String string ){System.out.println("holleworld:"+ string);}
校验通过。