通常情况来说,token失效会设计两种情况:
1.token在浏览器储存时间过长,过期失效;
2.同一个账号只能在一个浏览器登录存储token,在其他浏览器登陆上一个浏览器的账号会被抢占下线。
由于不停的更新token,对于浏览器来讲,负载是非常大的,对于用户来说,体验感也不好,试想使用手机时,每隔10分钟锁一次屏,所以我们用到另个一保存token状态的refresh token,来保持token的有效性。
一,使用场景
-
如果是一个前后端分离的项目,使用springsecurity+jwt这种,前端用户在登录以后,后端返回给前端一个accessToken,如果没有refresh token,又因为因为安全原因accessToken过期时间会设置的比较短,在accessToken过期以后,用户将会被强制重新登录,影响用户体验
而如果使用refresh Token,如果用户持续地访问这个网站,他们可以一直保持登录状态,而不需要定期重新登录。 -
如果是业务服务器之间的相互调用,那么此时只用一个Access Token即可,强制重新登录影响不大,只不过是如果使用 Refresh Token 在获取新的 Access Token 的时候比直接重新登录会方便一小丢丢(我复制的,其实个人觉得并不方便)。
二,使用流程
- 登录成功获得 refresh token 并持久化
- 通过 refresh token 请求刷新得到 access token 并临时储存
- 请求业务接口使用 access token
- access token 过期或者快过期再次回到「 2 」
- refresh token 也过期则生命周期结束,需重新登录
三,代码展示(需要的友友可以直接复制拿来用)
axios.interceptors.response.use(
response => {
const res = response.data;
if (response.status !== 200) { // 错误捕获处理
return Promise.reject(new Error(res.message || "Error"));
}
return res;
},
error => {
if (error.response.status === 401) {
if (!isRefreshing) {
isRefreshing = true;
//调接口,刷新token
return refresh({ // refresh是调用接口,从后台获取refresh token的方法
refToken: window.localStorage.getItem("refreshToken")
})
.then(result => {
if (result.data.access_token) {
// 刷新成功
window.localStorage.setItem(
"accessToken",
result.data.token_type + " " + result.data.access_token
);
window.localStorage.setItem(
"refreshToken",
result.data.refresh_token
);
error.config.headers.Authorization =
result.data.token_type + " " + result.data.access_token;
error.config.headers.withCredentials = true;
requestsList.length > 0 &&
requestsList.map(cb => {
cb();
});
requestsList = []; // 注意要清空
return axios(error.config);
} else {
// 刷新失败 退出登录
window.localStorage.clear();
router.push({
path: "/sso-login" + `?back=${encodeURIComponent(location.href)}`
});
}
})
.catch(err => {
//刷新失败 退出登录
window.localStorage.clear();
router.push({
path: "/login",
query: { redirect: router.currentRoute.value.fullPath }
});
return err;
})
.finally(() => {
isRefreshing = false;
});
} else {
// 正在刷新token ,把后来的接口缓冲起来
return new Promise(resolve => {
requestsList.push(() => {
error.config.headers.Authorization = window.localStorage.getItem(
"accessToken"
);
error.config.headers.withCredentials = true;
resolve(axios(error.config));
});
});
}
}
return Promise.reject(error);
}
);