RTau777

不断的学习,不断的充实

Springboot-如何使用注解在拦截器中进行权限判断

  在业务逻辑中,不同的角色拥有各自的职责,由于职责不同,所负责的功能也不一样,就拥有了不同的权限等级。

  而权限验证通常以拦截请求来实现,但不可能在每个Controller方法中都编写一段权限验证的代码,于是使用自定义注解就成了很好的解决方式。

示例

  假设有一个业务场景,需要判断用户所属的角色是否和要求角色匹配,那么可能需要进行如下操作:

@RequestMapping(value = "/addItem",method = RequestMethod.POST)
public Response addItemByAdmin(HttpServletRequest request,@RequestBody Map<String,Object> jsonObj){
    // 获取用户令牌
    String token = request.getHeader("Token");
    // 获取用户信息
    User user = userService.findUser(token);
    // 判断角色是否为管理员
    if(user.getRole()!=Role.ADMIN){
      // 若角色不匹配
      return Response.fail("只有管理员可以进行此操作");
    }
    // 如果角色匹配,进入业务流程
    .....
}

乍一看好像没有问题,但如果有很多业务场景都需要进行角色验证,那这段代码岂不是每个方法都要复制一遍?当然不行。

新建注解[1]

  示例demo提出的需求很简单,只需要一个角色信息即可完成业务,所以注解可以这样设计:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionLimit {
    // 注解需要设置的角色等级
    int role();
    // 管理员
    int ROLE_ADMIN = 103;
    // 会员
    int ROLE_VIP = 102;
    // 标准
    int ROLE_STANDARD = 101;
    // 被封禁
    int ROLE_LOCK = 100;
}
  1. 此处Target设置为METHOD,是因为一般不同请求会设置不同权限,如果需要按角色编写Controller,也可以将Target改为TYPE

在拦截器中配置验证

  需要先在拦截器中获取注解,使用注解中设置的角色对当前用户进行验证,若验证成功才能进入方法中执行业务流程。在拦截器的preHandle中进行如下操作:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws BusinessException {
    // 原拦截器操作
    .....
    // 角色验证
    if(!permissionLimit(request, handler)){
        return false;
    }
    // 其他
    .....
    return true;
}

private boolean permissionLimit(HttpServletRequest request, Object handler) throws BusinessException {
    // 如果不是方法
    if (!(handler instanceof HandlerMethod)){
        return true;
    }
    // 获取注解
    PermissionLimit pl = ((HandlerMethod)handler).getMethodAnnotation(PermissionLimit.class);
    // 如果没有注解就跳过
    if(pl == null){
        return true;
    }
    // 获取用户令牌
    String token = request.getHeader("Token");
    // 获取用户信息
    User user = userService.findUser(token);
    // 判断角色和注解的设置是否匹配
    return user.getRole()==pl.role()
}
  1. 此处抛出异常而不是直接返回响应信息是因为异常可被ExceptionHandler捕获,由它进行统一处理

使用方式

  示例中的方法此时可改为:

@PermissionLimit(role = PermissionLimit.ADMIN)
@RequestMapping(value = "/addItem",method = RequestMethod.POST)
public Response addItemByAdmin(@RequestBody Map<String,Object> jsonObj){
    // 进入业务流程
    .....
}



如有错误,欢迎指出,谢谢


  1. 创建自定义注解 ↩︎

posted on 2021-07-09 19:48  RTau777  阅读(511)  评论(0编辑  收藏  举报

导航

Powered by: 博客园
Copyright © 2021 RTau