在前端实现无感知刷新令牌(Token Refresh)是为了在用户访问应用程序期间,确保他们的身份认证令牌(通常是JWT)不会过期,以允许持续的用户会话而不需要重新登录, 一般前后端的交互是这样: 用户在前端登陆, 服务器返回两个token, 一个验证Token, 一个刷新Token, 平时请求携带的都是验证Token ,如果请求返回告知需要刷新则前端再做处理
以下是实现前端无感知刷新令牌的一般步骤和示例代码
身份认证令牌(Token)和刷新令牌(Refresh Token)
通常,身份认证令牌用于对用户进行身份验证和授权,而刷新令牌用于在身份认证令牌过期时获取新的身份认证令牌
检查到令牌过期
前后端一般会约定一个 code , 当请求返回该code时, 则代表身份认证令牌过期,在前端应用程序中,当该请求发送到服务器,服务器返回约定的 code 值时,即是需要刷新token 的时候
刷新令牌流程
这里我们可以使用发布订阅模式去处理刷新
- 在仓库管理中(vuex, pinia)设定一个布尔值
isRefresh, 一个数组requrestList,当返回约定code时,判断isRefresh是否为true,true 的话则把请求丢进一个请求队列requestList中(即订阅), false则把请求丢进队列同时去请求刷新token的接口 - 拿到刷新Token接口之后有两种情况, 如果失败,清空请求队列,随后根据业务做处理即可,一般是跳转登陆页,如果成功拿到的新的Token和refreshToken, 保存起来之后,重新将请求队列中的请求依次运行释放(即发布)
Token无感知刷新示例
axios中配置请求拦截
var isRefresh = false
var requestList = []
function refreshToken() {
// 写上你的刷新请求,以及请求成功后保存 Token 以及 循环等待请求队列
}
const instance = axios.create({
baseURL: import.meta.env.VITE_BASE_URL,
timeout: 30000,
withCredentials: true // send cookies when cross-domain requests
})
// axios 响应拦截
instance.interceptors.response.use(
(response) => {
if (response.data.code === 401) {
if(isRefresh) {
isRefresh = false
requestList.push(response.config)
refreshToken()
} else {
requestList.push(response.config)
}
}
return response.data
},
(error) => {
const { errorStore } = useStore()
LoadingUtils.hide()
const createTime: string = ToolUtils.getNowDateTimeCn()
const info = JSON.stringify(error)
errorStore.addError({ id: 0, url: window.location.href, title: error, info, createTime })
return Promise.reject(error)
}
)
export default instance