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;
}
- 此处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()
}
- 此处抛出异常而不是直接返回响应信息是因为异常可被ExceptionHandler捕获,由它进行统一处理
使用方式
示例中的方法此时可改为:
@PermissionLimit(role = PermissionLimit.ADMIN)
@RequestMapping(value = "/addItem",method = RequestMethod.POST)
public Response addItemByAdmin(@RequestBody Map<String,Object> jsonObj){
// 进入业务流程
.....
}
如有错误,欢迎指出,谢谢