一、认识什么是无感token刷新
1、首先认识一下什么是token,token是在当前前后端分类的架构中,重要的身份令牌 。
2、为什么会有无感刷新,因为在用户体验中,如果token失效,导致api请求失败,会严重影响用户的体验,无感刷新油然而生。
二、token无感刷新的思路
Access Token(访问token):用于api请求的身份认证,放在api请求头中用于身份验证
Refresh Token(刷新token):当前Access Token过期时, Refresh Token用来请求api,获取新的Access Token。
1、前端请求api,token过期
2、拿 Refresh Token去请求 刷新token的api,获取新的token,替换到旧的token。
3、(重点);api重试机制,触发401的api 需要在重新请求来实现真正的无感,让用户感受不到token过期。
三、贴代码示例
示例使用我的一个uni-app项目做讲解
1、请求刷新token的api方法
async function refreshAccessToken(): Promise<string> {
const rt = uni.getStorageSync('refreshToken')
if (!rt) {
throw new Error('refreshToken not found')
}
try {
const data = await $refreshToken({ refreshToken: rt })
uni.setStorageSync('token', data.accessToken)
uni.setStorageSync('refreshToken', data.refreshToken)
return data.accessToken
} catch { }
}
2、api触发401时 触发的关键代码。
export const resetToken = (config: any) => {
return new Promise((resolve, reject) => {
const queuedConfig = {
...config,
header: { ...(config?.header || {}) }
}
requestQueue.push({ config: queuedConfig, resolve, reject })
if (refreshingPromise) return
refreshingPromise = refreshAccessToken()
refreshingPromise
.then((newToken) => {
flushQueueWithToken(newToken)
})
.catch((err) => {
console.log('刷新token失败', err)
rejectQueue(err)
redirectToLoginOnce()
})
.finally(() => {
refreshingPromise = null
})
})
}
3、其他
`
function redirectToLoginOnce() {
if (hasRedirectedToLogin) return
hasRedirectedToLogin = true
uni.clearStorage()
uni.navigateTo({
url: '/pages/login/index'
})
}
function flushQueueWithToken(token: string) {
const pending = requestQueue.splice(0, requestQueue.length)
for (const task of pending) {
const retryConfig = {
...task.config,
_retry: true,
header: {
...(task.config?.header || {}),
Authorization: `Bearer ${token}`
}
}
uni.$uv.http.request(retryConfig).then(task.resolve).catch(task.reject)
}
}
function rejectQueue(error: any) {
const pending = requestQueue.splice(0, requestQueue.length)
for (const task of pending) {
task.reject(error)
}
}`