所有分类
  • 所有分类
  • 未分类

Shiro整合jwt-通过注解控制权限

简介

说明

本文介绍使用SpringBoot整合Shiro,使用jwt作为认证方式。

  1. 本文实操Shiro的使用。尽量使用原生的shiro配置,尽量少自定义配置。
  2. 使用jwt替代默认的authc作为认证方式,其他不变。
  3. 我自测通过,代码可用。

shiro用法我写了一个系列,有如下文章:

  1. Shiro整合jwt-通过注解控制权限 – 自学精灵
  2. Shiro整合jwt-通过url控制权限 – 自学精灵
  3. Shiro整合Session-通过注解控制权限 – 自学精灵
  4. Shiro整合shiro-redis – 自学精灵

使用形式

  1. 使用jwt替代默认的session来管理权限。
    1. 自定义jwt过滤器,并将其以“authc”为名字注册到Spring容器
  2. 使用角色和资源权限两种方式。(注解的方式)
  3. 使用Knife4j测试(Swagger的升级版)。
  4. 使用shiro-spring-boot-web-starter:1.7.0

技术栈

  1. shiro-spring-boot-web-starter:1.7.0
  2. spring-boot-starter-parent:2.3.8.RELEASE
  3. mysql:8.0
  4. mybatis-plus-boot-starter:3.4.3.1(持久层框架)
  5. lombok(简化代码)
  6. knife4j-spring-boot-starter:3.0.3(接口文档(swagger的升级版))

业务场景

本文假设做一个商城系统。

角色如下

  • admin:有所有权限
    • 使用shiro通配符:*:*
  • productManager:有product的所有权限
    • product:add,product:delete,product:edit,product:view
    • 本处把这四个权限单独赋予productManager这个角色,实际项目里可以将product:*这个权限赋予productManager这个角色。
  • orderManager:有order的所有权限
    • order:add,order:delete,order:edit,order:view
    • 本处把这四个权限单独赋予orderManager这个角色,实际项目里可以将order:*这个权限赋予orderManager这个角色。

用户密码及权限如下

用户密码角色拥有的权限
zhang312345admin所有权限。
li4abcdeproductManager产品的所有权限。

本处为了测试功能,赋予以下特殊权限:

  • 验证shiro可单独通过角色来控制权限
    • 给编辑订单接口设置角色权限:
      • @RequiresRoles(value = {“admin,productManager”}, logical = Logical.OR)
  • 验证shiro无法在一个接口上同时加@RequiresRoles和@RequiresPermissions
    • 给查看订单的接口设置角色权限与资源权限:
      • @RequiresPermissions(“order:view”)
        @RequiresRoles(value = {“admin,productManager”}, logical = Logical.OR)

结果展示

测试超级管理员(admin)

启动项目,访问:http://localhost:8080/doc.html

1.测试登录

  1. 登录成功
  2. 可以看到,会返回来一个Set-Cookie头,值是token。

2.测试有资源权限的接口

本处测试增加产品接口。

  1. 成功访问。
  2. 在请求时会传递Cookie

我使用标准的:Set-Cookie,Cookie来做认证的。若是自定义的header,需要手动写入:

3.测试登出

4.再次访问接口

  1. 访问成功。
  2.  因为token还没过期,浏览器也还会将其发给服务端,所以成功。

测试产品管理员(productManager)

启动项目,访问:http://localhost:8080/doc.html

1.测试登录

  1. 登录成功
  2. 可以看到,会返回来一个Set-Cookie头,值是token。

2.测试有资源权限的接口

本处测试增加产品接口。

  1. 成功访问。
  2. 在请求时会传递Cookie

3.测试无资源权限的接口

本处测试增加订单接口。

  1. 访问失败。
  2. 在请求时会传递Cookie
  3. 有一处细节:提示是红色的。这就是@ResponseStatus的作用

点进去看,可以看到状态码是我指定的:403

4.测试有角色权限的接口

本处测试编辑订单接口。

  1. 访问成功。
  2. 在请求时会传递Cookie

5.测试无角色权限的接口

本处测试删除订单接口。

  1. 访问失败。
  2. 在请求时会传递Cookie

测试同时有角色与权限注解

1.登录(productManager)

2.请求同时有角色和资源权限注解的接口

本处请求订单查看接口。

  1. 请求失败。
  2. 提示无资源权限。

由此推断,如果有两个注解,则必须同时满足这两个注解才可以。

3.登录(admin)

使用admin角色尝试,此角色同时有所有的资源权限。

4.请求同时有角色和资源权限注解的接口

本处请求订单查看接口。

  1. 请求成功

说明如果有两个注解,则必须同时满足这两个注解才可以。

重启服务再请求

1.登录

登录成功 

2.重启服务器

重启Idea启动的应用。

3.访问有权限的接口

本处访问产品增加接口。

  1. 可以看到,访问成功。

超时后再请求

1.修改配置文件,暂时将token过期时间改短(本处改为10秒)

application.yml

2.登录

3.等待大于10秒之后再请求

请求失败。

我代码里指定这种错误为401,点进去验证下:

代码

此内容仅限VIP查看,请先
0

评论12

请先

  1. 我把AuthConstant.AUTHENTICATION_HEADER=HttpHeaders.COOKIE改成AuthConstant.AUTHENTICATION_HEADER=HttpHeaders.SET_COOKIE,在谷歌上倒是满足了Set-Cookie,Cookie原则,倒是登录成功之后,访问其他请求返回的token是空的,无法解析,那可能是浏览器的原因了
    ynagtao已购买 2024-04-21 0
    • 是的,应该是浏览器问题了
      自学精灵 2024-04-22 0
  2. 站长有个疑问,为什么我在谷歌浏览器上返回token是Cookie,而不是Set-Cookie,导致无法传递到下一级,该如何设置?
    ynagtao已购买 2024-04-21 0
    • 我是在谷歌浏览器测试的,没问题。怀疑是你浏览器的问题,可以换个浏览器或者重装谷歌浏览器试试。
      自学精灵 2024-04-21 0
  3. 有个疑问,为什么在JwtFilter中的createToken方法返回的token值是请求时传进来的,既然用的是一样的为啥又要去做createToken新建这么个多余步骤
    150003 2024-04-16 0
    • 这个是shiro的代码流程,为了封装成它想要的结构
      自学精灵 2024-04-16 0
      • 为啥我的谷歌浏览器必须得用无痕模式才行,不然调接口一直被 if (!StringUtils.hasText(token)) 拦截没有token报错,而且不会自动保存cookie,只能手动加入到header里面
        150003 2024-04-16 0
        • 可能是你浏览器缓存的问题,可以进去清一下缓存试试
          自学精灵 2024-04-17 0
  4. 找到原因了,在Shiro.shiroFilterChainDefinition方法里的登录放行路径错了。 :cry:
    罖亽 2024-01-20 0
  5. 站长,所有请求都到 JwtFilter.onAccessDenied 方法这里,我第一次登录,是没有 token 的,直接在 if (!StringUtils.hasText(token)) 这里一直判定为 true 被拦截了,无法继续执行,该怎么解决这个问题啊?
    罖亽 2024-01-20 0
    • 将登录接口的url放到anon过滤器,这样就能跳过校验,往下执行。
      自学精灵 2024-01-20 0
显示验证码
没有账号?注册  忘记密码?

社交账号快速登录