vue+axios 使用JWT的时候如何使用refreshToken无痕刷新assetsToken并继续之前的请求?返回之前的数据?

什么是jwt

简单来说就是一个加密令牌,服务端能通过算法加密用户信息并随着请求和相应传送,进而能让服务端知道登录的是谁,他有没有权限进入我的服务器获取信息。jwt详细的实现方式就不在这里做赘述,有兴趣的小伙伴可以通过下方链接了解更多关于jwt的知识
JWT戳这里了解更多

为什么、怎么刷新token

我们在使用jwt的过程中,首先会接触到两个token,一个是accessToken,另一个是refreshToken,下面用atrt简写,at和rt都有对应的过期时间,当at过期的时候,使用rt调用接口来获取新的at和rt,那么我们保存在哪里?我选择的是保存在localStorage中,
第一次获取的token应该是在登录的时候拿到的,然后一直保存在localstroage中,每次请求我们都把at放在请求头auth中,这样随着请求和相应就可以实现JWT交互了。
上面说到,at、rt都有对应的过期时间,我们在at过期的之后,需要通过rt调用接口,获取新的at和rt,当我们使用rt的时候rt过期了怎么办?rt过期的话说明用户长时间没有操作,需要跳转到login页重新登录。

这过程中会有什么问题

在使用rt 刷新token的时候,如果用户当前有请求,那么这次请求会因为token过期而失败,如果前端会有提示的话,可能提示当前token已经过期,然后就不知道接下来的操作了。而前端此时应该是刷新完token,并继续之前的请求,或者说白了,刷新token这一步对于用户来说应该是无感的,用户应该时在不知情的情况下刷新token并拿到想要的数据,但是现在显然不是这样,因为过期报错请求已经终止了,用户在一脸懵逼中不知道发生了什么。

我的解决思路

第一种 因为时vue项目,使用axios来发送请求,第一时间就想到了拦截器,拦截器———拦截at刷新状态码——刷新token——??然后呢,然后该发送请求。但是我用了这种方法,不行。可能你有更好的方法,也请大神们指导我一下
第二种 中间层
没废话 直接贴代码

// require
const express = require('express')
const app = express()
const axios = require('axios')
const cors = require('cors')
let bodyParser = require('body-parser')
let qs = require('qs')
let fs = require('fs')

用express开启服务器,axios用来发送请求,cors配置跨域(因为没在同一个服务器上)qsfs解析body

var colors = require('colors');
// use
app.use(cors())
app.use(bodyParser.json())
app.use(
  bodyParser.urlencoded({
    extended: false
  })
)
const port = 4000

指定4000端口,use各插件

// router
app.post('*', function (request, response, next) {
  var path = request.path
  // 获取请求路径
  axios
    .post('http://192.168.35.161:8000' + path, qs.stringify(request.body), {
      headers: {
        authorization: request.headers.authorization || '',
        name: request.headers.name || ''
      }
    })
    .then(res => {
    // 请求发送的回调,70003,是token过期的状态码
      if (res.data.statusCode === 70003) {
      // 发送请求更新token
        axios
          .post(
            'http://192.168.35.161:8000/user-search/updateToken',
            qs.stringify({
              id: request.headers.id
            }), {
              headers: {
                authorization: request.headers.auth,
                name: request.headers.name
              }
            }
          )
          .then(function (res2) {
          // 更新token请求回调
            if (res2.data.statusCode === 70005) {
            //70005 更新失败状态码
              axios.post('http://192.168.35.161:8000' + path, qs.stringify(request.body), {
                headers: {
                  authorization: res2.data.data.accessToken,
                  name: request.headers.name
                }
              }).then(res3 => {
              // 拿到token过期的请求地址,重新发送请求,如何再把at和rt封装进返回的数据中去,一并发送给前端
                res3.data.refreshTokenData = {
                  accessToken: res2.data.data.accessToken,
                  refreshToken: res2.data.data.refreshToken
                }
                response.status(res3.status).send(res3.data)
              }).catch(error => {
              	// 出错返回异常
                response.status(error.response.data.status).send(error.response.data)
              })
            } else {
            // 出错返回异常
              response.status(res.status).send(res.data)
            }
          })
          .catch(function (error) {
          // 出错返回异常
            response.status(error.response.data.status).send(error.response.data)
          })
      } else {
      // 出错返回异常
        response.status(res.status).send(res.data)
      }
    }).catch(error => {
    // 打印本服务器的错误日志方便排错
      console.log(error)
      // 出错返回异常
      response.status(error.response.data.status).send(error.response.data)
    })
})




app.listen(port, () => console.log('服务启动成功,监听 ' + port + '端口!'))

我只想到这样做,大家有什么更好的方法可以下面交流!

你可能感兴趣的:(vue)