SpringBoot使用拦截器Interceptor实现统一角色权限校验

 更新时间:2023年07月17日 09:02:53   作者:天罡gg  
角色权限校验,是保证接口安全必备的能力:有权限才可以操作,所以,一般对于这种通用逻辑,推荐不与主业务逻辑耦合,那么怎么来解耦,那么本文小编就给大家详细讲解如何使用拦截器Interceptor实现统一角色权限校验,需要的朋友可以参考下

一、定义注解annotation

通用功能定义在tg-book-common中

我们最终实现的效果是:加了@Role注解以后,这个接口只有管理员才能访问,学生访问接口就会报错:无权限!

下面定义一个角色注解,通过@Target 指定作用于方法上。

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
    /**
     * 角色id数组,默认1-管理员
     **/
    int[] roleIds() default { 1 };
}

定义roleIds,是保留扩展性。若后面扩展出【校长】等其它角色,我们可以通过int数组来任意组合角色,只要拥有int数组中的任意角色id即可访问该接口。

二、拦截角色注解

1. 在拦截器哪里拦截?

显然,首先需要【用户身份认证】通过,然后再校验角色!即在AuthInterceptorpreHandle的保存至授权上下文之前:AuthContextInfo.setAuthInfo(authInfo); 

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    。。。省略一大堆用户身份认证代码。。。
    // TODO 校验角色:写在这!
    // 校验成功, 保存至认证上下文
    AuthContextInfo.setAuthInfo(authInfo);
    return true;
}

2. 如何拦截角色注解?

可以通过将handler转成HandlerMethod以后,通过getAnnotation来获取!

HandlerMethod handlerMethod = (HandlerMethod) handler;
Role role = handlerMethod.getMethod().getAnnotation(Role.class);
if (role != null) {
    // 走到这,说明方法上加了@Role
}

3. 角色如何读取?

前2步以后,我们就拿到了当前登录的userId,也拿到了接口要求的roleIds数组,所以至少有两种方案:

  1. 可以通过userId去查一次MySQL,然后判断一下角色,这种我就不实现了,你可以自己去查询实现!
  2. 将roleId保存在token中!,本文实现的是另一种方案,是为了扩展一下大家的思路,也就是不走MySQL查询的方案。

AuthContextInfo类中增加字段来承载角色:

private Integer roleId;

loginByPassword中将role设置到authContextInfo.roleId

authContextInfo.setRoleId(user.getRole());

接着在JwtTokenProvider中定义payload的自定义字段r:

// payload的自定义字段r
private static final String CLAIM_ROLE = "r";

在JwtTokenProvider.create中将它保存到token的payload中:

// 自定义 role
.withClaim(CLAIM_ROLE, authContextInfo.getRoleId())

在JwtTokenProvider.verify中将它从token中解析出来:

4. 最后做角色校验

拿到了authInfo.getRoleId(),还知道了接口方法要求的roleIds,判断逻辑太简单了吧~ 我简单写了一下,如下:

// 校验角色
HandlerMethod handlerMethod = (HandlerMethod) handler;
Role role = handlerMethod.getMethod().getAnnotation(Role.class);
if (role != null) {
    // 走到这,说明方法上加了@Role
    boolean isAdmin = false;
    for (int roleId : role.roleIds()) {
        if (authInfo.getRoleId().equals(roleId)) {
            isAdmin = true;
            break;
        }
    }
    if (!isAdmin) {
        log.info("[403]无权限, token={}", token);
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        // 别忘了返回false
        return false;
    }
}

三、应用:给管理员操作接口加注解

在实现了通用校验逻辑以后,接下来就是如何应用了!
其实就是:加@Role注解

下面对管理员录入和修改图书接口加了注解,其它接口同理~~

四、PostMan测试

使用role=0的账号调用管理员API,返回403!

使用管理员账号则会正常执行!就不做截图了!另外,别忘了提交Git!

以上就是SpringBoot使用拦截器Interceptor实现统一角色权限校验的详细内容,更多关于SpringBoot Interceptor统一角色权限校验的资料请关注脚本之家其它相关文章!

相关文章

  • java绘制五子棋棋盘

    java绘制五子棋棋盘

    这篇文章主要为大家详细介绍了java绘制五子棋棋盘,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01
  • 基于SpringBoot+AOP实现接口限流

    基于SpringBoot+AOP实现接口限流

    本文介绍了使用SpringBoot和AOP实现接口限流的方法,通过自定义注解、限流工具类、AOP切面等实现限流功能,支持多种限流策略、粒度和存储方式,并提供了详细的代码示例和测试验证方法,需要的朋友可以参考下
    2026-04-04
  • System.currentTimeMillis()计算方式与时间的单位转换详解

    System.currentTimeMillis()计算方式与时间的单位转换详解

    这篇文章主要介绍了System.currentTimeMillis()计算方式与时间的单位转换详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • java 中死锁问题的实例详解

    java 中死锁问题的实例详解

    这篇文章主要介绍了java 中死锁问题的实例详解的相关资料,希望通过本文大家能够理解掌握死锁的问题,需要的朋友可以参考下
    2017-09-09
  • java实现简单的小超市程序

    java实现简单的小超市程序

    这篇文章主要为大家详细介绍了java实现简单的小超市程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-02-02
  • Java网络编程UDP协议发送接收数据

    Java网络编程UDP协议发送接收数据

    这篇文章主要为大家详细介绍了Java网络编程UDP协议发送接收数据,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • redisson常用加锁方式详解

    redisson常用加锁方式详解

    文章介绍了两种Redisson加锁方式的区别:基本的RLock方式和使用RedissonDistributedLocker的tryLock方式,RLock需要手动处理锁的等待和持有时间,而tryLock则提供了更高层次的封装,简化了锁的操作,并且在超时后会自动返回或释放锁
    2026-01-01
  • Java RPC框架过滤器机制原理解析

    Java RPC框架过滤器机制原理解析

    这篇文章主要介绍了Java RPC框架过滤器机制原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Java如何优雅替换if-else语句

    Java如何优雅替换if-else语句

    当逻辑分支非常多的时候,if-else套了一层又一层,那么如何干掉过多的if-else,本文就详细的介绍一下,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • java实现jframe透明窗体示例

    java实现jframe透明窗体示例

    这篇文章主要介绍了java实现jframe透明窗体示例,需要的朋友可以参考下
    2014-03-03

最新评论