思路:
根据自定义注解,给对应权限能够查看到的资源的Controller方法上添加注解(也就是一个权限字符串),权限字符串跟方法是一对多的关系,同一个权限字符串可以添加到多个方法上;当用户有对应的权限时才能查看对应的资源;
所以我们可以获取到用户所拥有的所有权限字符串集合(登录时获取到,放入令牌池) & 当前所访问的方法对应的权限字符串(反射动态获取方法上的注解) => 判断集合中是否有这一个
创建一个anno包,包里创建PreAuth,注意PreAuth是Annotation类型的,PreAuth是用来写自定义注解的
/**
* @Author liu-miss
* @Description //权限校验注解
* @Date l 2021/8/19
**/
@Target({ElementType.METHOD}) //该注解可以作用到哪些类型元素上:有,ElementType.METHOD(方法)、ElementType.TYPE(类)、字段;若是ElementType.METHOD(方法),则只能加在方法上
@Retention(RetentionPolicy.RUNTIME) //运行时生效
public @interface PreAuth {
/**
* @Author liu-miss
* @Description //权限字符串
* @Date l 2021/8/19
**/
String value() default "";
}
需要在实体类中加一个存放权限字符串的集合 private List authList =》 用来存放权限字符串,并加上相应的 get 和 set 方法
private List<String> authList;
public List<String> getAuthList() {
return authList;
}
public void setAuthList(List<String> authList) {
this.authList = authList;
}
我们需要写一个根据用户id添加权限字符串的方法,存放到权限字符串集合中
Service层:
List<String> listAuthListByuserId(Long userId);
对应的实现方法ServiceImpl层:
@Override
public List<String> listAuthListByuserId(Long userId) {
/**
* 多对多查询
* 用户id -> 用户-角色的多对多关联表 -> 角色 -> 角色和菜单的多对多关联表 -> 菜单 -> 权限字符串
*/
List<String> authList = new ArrayList<>();
//添加user:view的权限字符串,权限字符串为user:view的都可以访问到
authList.add("user:view");
return authList;
}
接下来就应该在拦截器中进行验证了
利用反射,获取目标方法的注解,利用获取到的注解判断用户是否有这个权限去访问
// 接收访问的目标方法信息
HandlerMethod handlerMethod = (HandlerMethod)handler;
// 获取目标方法上的指定注解
PreAuth preAuth = handlerMethod.getMethodAnnotation(PreAuth.class);
System.out.println("当前方法的权限字符串为:"+preAuth);
if(preAuth == null){
// 不需要验证权限
return true;
}
// 判断用户是否拥有该方法的访问权限
List<String> authList = user.getAuthList();
if(!authList.contains(preAuth.value())){
System.err.println("权限验证失败!");
// 没有,返回false
return false;
}
// 当返回true的时候,验证成功,可以继续向下执行,访问目标方法
return true;
在能使用这个权限字符串访问到的Controller层方法中加上@PreAuth(“user:view”)即可访问到
在Postman中测试:
有权限:
如果没有权限: