# RefreshToken机制

# 需求分析

用户token不能设置太长的有效时间,这样可以提高接口部分的安全性。

refreshToken

说明:

  • 登录请求/login成功之后会响应token&refreshToken;
  • token的过期时间比较短,比如1小时到4小时,refreshToken的过期时间比token要长,比如1天或者7天;
  • 用户在登录之后,所有的鉴权的接口带上token;
  • 如果token过期,则使用refreshToken进行请求/login/refresh接口,请求新的token;
  • 如果refreshToken未过期,则返回新token;
  • 如果refreshToken过期,则返回401;

# 创建refreshToken接口

添加src/routes/modules/loginRouter.js路由:

// refresh
router.post('/refresh', loginController.refresh)

调整登录接口src/api/LoginController.js

  // 微信登录
  async wxLogin (ctx) {
  // 1.解密用户信息
    const { body } = ctx.request
    const { user, code } = body
    if (!code) {
      ctx.body = {
        code: 500,
        data: '没有足够参数'
      }
      return
    }
    const res = await wxGetUserInfo(user, code)
    if (res.errcode === 0) {
    // 2.查询数据库 -> 判断用户是否存在
    // 3.如果不存在 —> 创建用户
    // 4.如果存在 -> 获取用户信息
      const tmpUser = await User.findOrCreateByUnionid(res)
      // 5.产生token,获取用户的签到状态
      const token = generateToken({ _id: tmpUser._id })
      const userInfo = await addSign(tmpUser)
      ctx.body = {
        code: 200,
        data: userInfo,
        token,
        // 新增refreshToken
        refreshToken: generateToken({ _id: tmpUser._id }, '7d')
      }
    } else {
      ctx.throw(501, res.errcode === 40163 ? 'code已失效,请刷新后重试' : '获取用户信息失败,请重试')
    }
  }

  // refreshToken
  async refresh (ctx) {
    ctx.body = {
      code: 200,
      token: generateToken({ _id: ctx._id }, '60m'),
      msg: '获取token成功'
    }
  }

# 前端页面逻辑

  • 错误拦截中,针对 401的情况进行单独处理;
    • 返回401之后,使用新的request实例请求refreshToken的接口;
    • 请求成功之后,更新本地的token及缓存;
  • 使用新的Token重新发发起旧的请求;

# 登录失败后处理缓存

src/store/index.js中新增关于清除token及用户信息的actions

const actions = {
  logout ({ commit }) {
    commit('setToken', '')
    commit('setUserInfo', {})
    commit('setRefreshToken', '')
    uni.clearStorage()
  }
}

最终测试与效果:

image-20210802192754262