关键词:刷新JWT,更新,缓存

平台:数据库(mongodb, mysql),redis

首先在用户注册的时候,我们需要收集用户的账号信息 譬如 id + username + 乱七八糟mix salt 的组合用md5加密成一串用户初始token,和用户信息一起存入数据库,作为用户在平台唯一识别token(注意这个token和jwt发的token不是一回事)。

在用户注册登录的时候就把上述token作为cookie塞给用户浏览器,存在redis维护一份(这里看策略,一般可能2-4小时后失效),redis保存信息形式大概为token:{用户基本信息}
【下面的代码仅为思路展示,像很多sql和redis操作不能直接套用,仅供参考】

async login(*ctx*, *next*) {
​      try {
​        const {username, pwd} = await Util.treamentFormData(ctx.req)
​        const handlePsw = md5Pwd(pwd)
​        const getCheckUserInfo = await query(
​          `SELECT FROM users WHERE name = ${username} AND vkey = ${handlePsw}`
​        )
​        if (!getCheckUserInfo) {
​          return ctx.body =({code: 1, msg: '用户名或密码错误'})
​        } else {
​          const userInfo = {username: findOneRes.username, vkey: findOneRes.vkey}
​          const token = Util.setToken(userInfo)
​          const redis = initStone() 
​          redis.set(findOneRes.vkey, JSON.stringify(userInfo) , 'EX', 60 * 60 * 2) *//秒为单位 2个小时redis失效*
​          const CookieOpt = CookieConfig()
​          try {
​            ctx.cookies.set('_token', findOneRes.vkey, CookieOpt)
​          } catch(err) {
​            console.log(err)
​          }
​          ctx.response.body = ({code: 0, data: {...findOneRes._doc, token}})
​        }
​      } catch (e) {
​        ctx.response.body = e
​      }
  },

基于jwt有时效性我们前端调用的时候先查验一下jwt的有效时间,这里可以发起一个请求去获取最新的jwt,使用cookie作为凭据(所以这个cookie的时间可以设长一点,比如一个月),然后使用全局变量维护这个拿下来的jwt,当下一个接口请求的时候,会先去本地拿这个对象看看过没过期,如果过期了,去调这个获取jwt的接口再拿一次新的,这个接口返回新的token和用户个人信息

  *// 处理鉴权 不刷新cookie*
  async accessToken(*ctx*, *next*) {
​    try {
​        const getCookie = ctx.request.header.cookie
​       if (getCookie) {
​          *// redis.set('DD', 100, 'EX', 5) //秒为单位*
​          const parseCookie = Util.handleCookie(getCookie)
​          const getCookieToken = parseCookie['_token']
​          const redis = initStone() 
​          const result = await redis.get(`${getCookieToken}`)
​          if (result) {
​            const userInfo = JSON.parse(result)
​            const newToken = Util.setToken(userInfo)
​            ctx.body = ({code: 0, msg: 'success' , data: {token: newToken, userInfo}})
​          } else {
​            const getUserInfo = await query(
​              `SELECT FROM users WHERE vkey = ${handlePsw}`
​            ) 
​            if (getUserInfo) {
​              redis.set(getUserInfo.vkey, JSON.stringify(getUserInfo) , 'EX', 60 * 60 * 2) *//秒为单位 2个小时redis失效*
​              const newToken = Util.setToken(getUserInfo)
​              ctx.body = ({code: 0, msg: 'success' , data: {token: newToken, getUserInfo}})
​            } 
​          }
​       } else {
​          ctx.status = 401
​          ctx.body = ({code: -1, msg: 'fail'})
​       }
​    }  catch(e) {
​       console.log(e)
​    }
  }

这里通过cookie的toke去获取用户信息,如果redis上有这个信息(即_token = redis上的key "_token"),直接使用redis上的信息颁布新的jwt,如果没有,则通过这个token我们可以去查询数据里面个人信息,查到后再塞一次到redis,并且再返回个人信息和新的jwt给前端。

{
​    account: {
​        username: '',
                token: ''
​        …otherInfo,
​    }
}
preView