關(guān)鍵詞:刷新JWT,更新严里,緩存
平臺:數(shù)據(jù)庫(mongodb, mysql),redis
首先在用戶注冊的時候追城,我們需要收集用戶的賬號信息 譬如 id + username + 亂七八糟mix salt 的組合用md5加密成一串用戶初始token刹碾,和用戶信息一起存入數(shù)據(jù)庫,作為用戶在平臺唯一識別token(注意這個token和jwt發(fā)的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有時效性我們前端調(diào)用的時候先查驗一下jwt的有效時間火诸,這里可以發(fā)起一個請求去獲取最新的jwt锦针,使用cookie作為憑據(jù)(所以這個cookie的時間可以設(shè)長一點,比如一個月)置蜀,然后使用全局變量維護這個拿下來的jwt奈搜,當(dāng)下一個接口請求的時候,會先去本地拿這個對象看看過沒過期盯荤,如果過期了馋吗,去調(diào)這個獲取jwt的接口再拿一次新的,這個接口返回新的token和用戶個人信息
*// 處理鑒權(quán) 不刷新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我們可以去查詢數(shù)據(jù)里面?zhèn)€人信息绍哎,查到后再塞一次到redis,并且再返回個人信息和新的jwt給前端芥玉。
{
? account: {
? username: '',
token: ''
? …otherInfo,
? }
}