vue项目中使用axios,拦截器实现自动刷新token机制,拦截请求队列
管理系统项目,基于vue+axios,使用axios拦截器实现自动刷新token机制整个项目的首次登录会获取到用户的token,refreshToken,expires_intoken为本次登录的请求凭证,有效期较短,使用expires_in与当前时间戳进行比较,判断是否过期,一般为两个小时,若过期,需要使用refreshToken重新换取refreshToken是用来刷新token的凭证...
·
管理系统项目,基于vue+axios,使用axios拦截器实现自动刷新token机制
整个项目的首次登录会获取到用户的token,refreshToken,expires_in
- token为本次登录的请求凭证,有效期较短,使用expires_in与当前时间戳进行比较,判断是否过期,一般为两个小时,若过期,需要使用refreshToken重新换取
- refreshToken是用来刷新token的凭证,作为获取当前token接口的参数,换取新一轮的token,有效期较长,一般为半个月,若过期,需要重新登录获取
- expires_in是当前token过期时刻的时间戳,一般会在距离过期前10分钟,重新请求新一轮的token
嘿嘿~~~~~~~废话不多说,贴一段代码!(本人亲测有效!)
/* 是否有请求正在刷新token */
window.isRefreshing = false
/* 被挂起的请求数组 */
let refreshSubscribers = []
/* push所有请求到数组中 */
function subscribeTokenRefresh(cb) {
refreshSubscribers.push(cb)
}
/* 刷新请求(refreshSubscribers数组中的请求得到新的token之后会自执行,用新的token去请求数据) */
function onRrefreshed(token) {
refreshSubscribers.map(cb => cb(token))
}
const fetch = axios.create({
baseURL: '',
timeout: '30000'
})
function computedTime() {
let r = getRefresh();
if (!r || !r.expires_in) return false;
let currentTime = Date.parse(new Date()) / 1000;
let expiresTime = r.expires_in;
// 600秒后即将过期,true则不需要刷新
return expiresTime - currentTime <= 600
}
fetch.interceptors.request.use(async (config) => {
if (config.url !== '/oauth/token') {//获取token的接口不进行拦截
getToken() && (config.headers.Authorization = getToken());
if (computedTime()) {
if (!window.isRefreshing) {
window.isRefreshing = true;
let r = getRefresh();
if (!r) return;
let refreshData = {
grant_type: 'refresh_token',
client_id: r.client_id,
client_secret: r.client_secret,
refresh_token: r.refresh_token
}
getTokens(refreshData).then((data) => {
window.isRefreshing = false;
let rData = {
client_id: r.client_id,
client_secret: r.client_secret,
expires_in: (Date.parse(new Date()) / 1000 + data.expires_in),
grant_type: 'refresh_token',
org_id: r.org_id,
refresh_token: r.refresh_token
}
// 存储token,存进cookie里面
store.commit('setTokenInfo', data.token_type + data.access_token);
// 存储refresh_token
store.commit('setRefreshToken', rData);
onRrefreshed(data.token_type + data.access_token);
/* 执行onRefreshed函数后清空数组中保存的请求 */
refreshSubscribers = [];
}).catch(err => {
console.log(err);
router.replace({
path: '/login'
})
})
}
/* 把请求(token)=>{....}都push到一个数组中 */
let retry = new Promise((resolve, reject) => {
/* (token) => {...}这个函数就是回调函数 */
subscribeTokenRefresh((token) => {
config.headers.Authorization = token
/* 将请求挂起 */
resolve(config)
})
})
return retry
} else {
return config
}
} else {
return config
}
}, (error) => {
return Promise.reject(error);
})
这样就可以实现,在距离token过期十分钟之后的请求,都会先进行一次token的刷新,并且同时将马上要发起的几个请求放在一个promise的队列当中,等到我的token利用refreshToken刷新到新的token之后,再去取队列当中的http请求,遍历在header头部Authorization添加新的token。再继续发起请求,之后 注意 要清空掉队列中http请求哦~~~~
但是对于用户端来说,(发生了什么,我不清楚???)是没有一点感觉哒,用户体验灰常好~~~
感觉下面大神的分享??
更多推荐
已为社区贡献2条内容
所有评论(0)