关键词:刷新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,
}
}