Springboot2.x 整合shiro JWT redis 前后端分离

前言

原文地址:Springboot2.x 整合shiro JWT redis 前后端分离

如果你还对Shiro不太了解,请先看完上个教程:springboot2.x 整合shiro
本文整合shiro与JWT,其中数据库采用 用户->角色->权限 三层,JWT有token和refreshToken,其中refreshToken存储用的是redis,下面我们会一一介绍。

正文

流程

我们先说一遍用户请求的大概流程,其中涉及到了refreshToken的使用,如果不太懂的话可以看一下refreshToken的介绍(在本文下方会提到)。或者你在阅读下面过程中有不懂的,也可以直接跳转到下面的refreshToken介绍。

获取token:
  1. 用户第一次登陆,用户名密码请求登录接口
  2. 登录接口判断是否正确,正确发送Token,并创建refreshToken(包含发布token的时间)定时(过期时间)存储至redis
  3. 修改响应头 Authorization : token
携带 正常token 请求:
  1. 用户携带token请求 需要权限接口
  2. shiro拦截用户请求,验证token是否正确,是否未过期,验证redis中的refreshToken是否匹配传入的Token(两者发布时间是否一致)
  3. 上述验证通过后,根据token中的用户信息获取对应的角色信息和权限信息
  4. 权限信息验证是否与请求所需的权限相同(shiro完成),通过后进入接口返回数据,不通过返回报出权限异常
携带 过期token 请求:
  1. 用户携带过期的token请求(refreshToken确保未过期)需要权限的接口;
  2. shiro拦截用户请求,验证token是否正确,发现已经过期,抛出过期的异常
  3. 拦截器捕获异常,并查找redis中的refreshToken,对比两者是否匹配(两者的签发时间是否一致)
  4. 一致则重新生成新的token,修改响应头 Authorization : token,并修改refreshToken值(过期时间不会被修改)
  5. 再次验证通过后,根据token中的用户信息获取对应的角色信息和权限信息
  6. 权限信息验证是否与请求所需的权限相同(shiro完成),通过后进入接口返回数据,不通过返回报出权限异常

数据库设计

基于RBAC设计的基础权限模型,大家可以自行百度一下RBAC,目前也是非常主流的权限模型,很多权限设计都是由它进行变形:

具体设计:

在这里插入图片描述

Token 与 refreshToken

Token就不写了,自行百度吧…

refreshToken是OAuth2.0中颁布的,用于刷新过期token,减少用户登录次数的一个存储在服务器端的token。

这边放一个链接,这里不再细讲:OAuth2.0关于刷新token的问题

关于刚才流程中的Token问题:

1. 为什么每次验证token都需要与refreshToken匹配?
  • token与refreshToken验证一个是验证token的是不是最新的(签发时间对比),这样也就是可以单点登录

  • 可以通过删除refreshToken达到强制下线的效果。

2. 为什么利用refreshToken刷新token时不刷新refreshToken过期时间?

额…貌似两种思路。我感觉不刷新refreshToken会更好一点,一旦有人盗用了你的token,那么他每隔一段时间请求一下,就可以一直用下去。
所以refreshToken过期需要重新登陆,及时止损…

编写代码

我们不再讲解shiro的基础使用方法,如果你还不知道,需要再看一遍我上一篇的教程:springboot2.x 整合shiro。当然如果你是大佬,你可以点个赞然后按下calt+w了…

引入JWT

        <!--jwt-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.1</version>
        </dependency>

基本的Jwt类

jwt基础类
/**
 * @Author: goodtimp
 * @Date: 2019/10/1 22:22
 * @description :  token
 */
public class JwtToken implements AuthenticationToken {
   
    private String token;

    public JwtToken(String token) {
   
        this.token = token;
    }

    @Override
    public Object getPrincipal(){
   
        return token;
    }

    @Override
    public Object getCredentials(){
   
        return token;
    }
}
jwt工具类

/**
 * @Author: goodtimp
 * @Date: 2019/10/1 22:44
 * @description :  jwt工具类
 */
public class JwtUtil {
   
     /**
     * 验证token是否正确
     *
     * @param token
     * @return
     */
    public static boolean verify(String token) {
   
        try {
   
            String secret = ; // 这个自己要去定义,用来加密token做验证的
            Algorithm algorithm = Algorithm.HMAC256(secret);  // 解密 验证正确性
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (UnsupportedEncodingException e) {
     // 不报异常就是正确的
            logger.error("JWTToken认证解密出现UnsupportedEncodingException异常:" + e.getMessage());
            throw new TokenException("JWTToken认证解密出现UnsupportedEncodingException异常:" + e
  • 5
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值