主要注解
@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";
@Resource
private 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);
}
校验通过。