如何实现token的无感刷新

为了确保用户在整个会话的期间保持登录状态,无需多次认证,我们需要做到无感刷新token
首先当我们用户登录的时候会生成两个token,

Token:存放一些用户非私密信息  ,时间较短  一两个小时即可
RefreshToken: 只存放用户的id  ,时间较长 两三个月集或更长

生成的两个token我们需要保存本地存储中,当我们请求的时候携带token进行访问,后台会验证token是否过期,没有过期则正常访问资源,如果过期后台会返回一个状态到前台,前台在拦截器中对这个状态进行判断,如果真的过期了前台就会调用一个更新token的接口并将RefreshToken作为参数携带过去,然后后台对RefreshToken进行校验查看是否是有效令牌,查看完成后会生成新的token 和 RefreshToken返回给前台,然后存储,携带访问即可
在这里插入图片描述

前端

  // 添加响应拦截器
    this.myAxios.interceptors.response.use(
      async function (response: any) {
        //关闭loading层
        closeNotify();
        const { code, msg, data } = response.data;

        if (code === 0) {
          return data;
        } else if (code == undefined) {
          return response;
        } else if (code == 457) {
          try {
            // 刷新token
            await refreshToken();
            // 重新执行请求
            return that.myAxios(response.config);
          } catch(error: any) {
            showNotify({type: 'danger',message: error.message})
            return Promise.reject(error)
          }
        } else if (code != 0) {
          return Promise.reject(msg);
        }
      },
      function (error: any) {
        // 对响应错误做点什么
        closeNotify();
        return Promise.reject(error);
      }
    );
  }
const refreshToken = async () => {
    closeNotify();
  return await axios
    .get("/apis/bm-member-service-app/api/member/refresh_token", {
      params: {
        refreshToken: beimao_store.refreshToken,
      },
    })
    .then(function (response) {
      const { code, msg, data } = response.data;
      if (code != 0) {
        return Promise.reject(new Error(msg));
      }

      beimao_store.token = data.token;
      beimao_store.refreshToken = data.refreshToken;
      return Promise.resolve("成功");
    })
    .catch(function (error) {
      return Promise.reject(new Error("稍等稍等"));
    });
};

后端

    /**
     * 刷新token
     * @param refreshToken
     * @return
     */
    @GetMapping("/refresh_token")
    public Map<String,String> login(String refreshToken) {
        return loginService.refresToken(refreshToken);
    }
 public Map<String, String> refresToken(String refreshToken) {

        if(ObjectUtil.isEmpty(refreshToken)){
            throw new BizException(456,"token必传");
        }
        boolean b = false;
        // 验证算法,JWTValidator包含过期的验证,验证比较全面
        try {
            JWTValidator.of(refreshToken).validateAlgorithm(JWTSignerUtil.hs256(key.getBytes())).validateDate();
            b = true;
        }catch (Exception ex){
            ex.printStackTrace();
        }
        if(!b){
            throw new BizException(457,"token不正确");
        }
        //{id:8,nickName:“张麻子”}
        //ThreadLocal 作用 能够跨类跨方法实现变量共享

        JSONObject jsonObject = JSONUtil.toBean(JWTUtil.parseToken(refreshToken).getPayload().toString(), JSONObject.class);
        int id = Integer.parseInt(jsonObject.get("id").toString());

        Member member = loginDao.selectById(id);
        if(ObjectUtil.isEmpty(member)){
            throw new BizException(610,"账号或密码错误");
        }
        //设置双Token
        //带参数的设置短时间
        Map<String , Object> map1 = new HashMap<String,Object>(){
            private static final long serialVersionUID = 1L;
            {
                put("id", member.getId());
                put("nickName", member.getNickName());
                put("exp", System.currentTimeMillis()/1000 + 10);
            }
        };
        //不带参数的设置长时间
        Map<String , Object> map2 = new HashMap<String,Object>(){
            private static final long serialVersionUID = 1L;
            {
                put("id", member.getId());
                put("exp", System.currentTimeMillis()/1000 + 1000 * 60 * 60 * 24 * 30 * 2);
            }
        };
        String token = JWTUtil.createToken(map1,key.getBytes());
        String refreshToken2 = JWTUtil.createToken(map2,key.getBytes());
        //将Token存入map返回出去
        Map<String ,String> map = new HashMap<>();
        map.put("token", token);
        map.put("refreshToken", refreshToken);
        return map;
    }
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值