vue下axios攔截器token刷新機制的實例代碼
更新時間:2020年01月17日 13:42:15 作者:cxf2018
這篇文章主要介紹了vue下axios攔截器token刷新機制的實例代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
//創(chuàng)建http.js文件,以下是具體代碼:
//引入安裝的axios插件
import axios from 'axios'
import router from '@/router';
import Vue from 'vue'
const qs = require("qs");
let _this = new Vue();
let isLock = false;
let refreshSubscribers = [];
//判斷token是否過期
function isTokenExpired(token) {
let expires_time = JSON.parse(token).expires_time;
let curentTime = new Date().getTime();
if (curentTime >= expires_time) {
return true;
} else {
return false;
}
}
//獲取Token對象
function getToken() {
return localStorage.getItem("token");
}
//push所有請求到數(shù)組中
function subscribeTokenRefresh(cb) {
refreshSubscribers.push(cb)
}
//刷新請求(refreshSubscribers數(shù)組中的請求得到新的token之后會自執(zhí)行,用新的token去請求數(shù)據(jù))
function onRrefreshed(token) {
refreshSubscribers.map(cb => cb(token))
}
//刷新token
function refreshToken(config, token, resolve, reject) {
let data = { refresh_token: JSON.parse(token).refresh_token };
axios({
method: "post",
url: "xxxxxx/refreshToken",//刷新token的接口
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic b3JkZXItc2VydmVyOjEyMzQ1Ng=="
},
data: qs.stringify(data)
}).then(res => {
isLock = false;//釋放鎖
if (res.data.code === 101) {
_this.$message.error('登錄狀態(tài)已失效,請重新登錄。');
localStorage.removeItem("token");
router.push({
path: "/login"
});
return;
}
let expires_time = new Date().getTime() + parseInt(res.data.data.expires_in * 0.8) * 1000;
let token = JSON.parse(localStorage.getItem("token"));
token.expires_time = expires_time;
token.access_token = res.data.data.access_token;
localStorage.setItem("token", JSON.stringify(token));
config.headers.Authorization = 'Bearer ' + res.data.data.access_token;
resolve(config);
//執(zhí)行數(shù)組里的函數(shù),重新發(fā)起被掛起的請求
onRrefreshed(res.data.data.access_token)
//清空數(shù)組中保存的請求
refreshSubscribers = []
}).catch(err => {
return err;
});
}
function request(newOptions, resolve, reject) {
axios({
method: newOptions.method,
url: newOptions.url,
data: newOptions.type == "form" ? qs.stringify(newOptions.data) : newOptions.data,
headers: newOptions.headers
}).then(res => {
if (res.status == 200) {
//這里我們只需要獲取返回的data中的數(shù)據(jù)即可
resolve(res.data);
} else {
reject(res.data);
}
}).catch(err => {
reject(err);
_this.$message.error('服務(wù)異常!');
})
}
axios.interceptors.request.use(
config => {
let token = getToken();
if (token) {
//判斷token是否過期,如果過期請求刷新token
if (isTokenExpired(token)) {
//判斷當(dāng)前是否正在請求刷新token
if (!isLock) {
isLock = true;//isLock設(shè)置true,鎖住防止死循環(huán)。
//使用Promise等待刷新完成返回配置信息
let refresh = new Promise((resolve, reject) => {
refreshToken(config, token, resolve, reject);
})
return refresh;
} else {
//判斷當(dāng)前url是否是刷新token的請求地址,如果是直接下一步。
if (config.url.indexOf('/logined/refreshToken') === -1) {
//把請求(token)=>{....}都push到一個數(shù)組中
let retry = new Promise((resolve, reject) => {
//(token) => {...}這個函數(shù)就是回調(diào)函數(shù)
subscribeTokenRefresh((token) => {
config.headers.Authorization = 'Bearer ' + token
//將請求掛起
resolve(config)
})
})
return retry
} else {
return config;
}
}
} else {
return config;
}
} else {
return config;
}
}, error => {
return Promise.reject(error);
});
const http = options => {
return new Promise((resolve, reject) => {
const defaultOptions = {
type: "json"
};
const newOptions = {
...defaultOptions,
...options
};
//headers默認(rèn)傳遞json格式數(shù)據(jù),這里也可以設(shè)置token,每次調(diào)用都會攜帶
if (localStorage.getItem("token")) {
newOptions.headers = {
// 'Authorization': 'Basic b3JkZXItc2VydmVyOjEyMzQ1Ng==',
'content-Type': newOptions.type == 'form' ? 'application/x-www-form-urlencoded;charset=UTF-8' : 'application/json;charset=UTF-8',
'Authorization': 'Bearer ' + JSON.parse(localStorage.getItem("token")).access_token,
...newOptions.headers
};
} else {
newOptions.headers = {
'content-Type': newOptions.type == 'form' ? 'application/x-www-form-urlencoded;charset=UTF-8' : 'application/json;charset=UTF-8',
...newOptions.headers
};
}
request(newOptions, resolve, reject);
})
};
//設(shè)置請求超時
axios.defaults.timeout = 30000
export default http
//在main.js下面掛載 http.js文件
import http from '@/utils/http.js';
Vue.prototype.http = http;
//登錄保存token信息接口
this.http({
method: "post",
url: "/xxxxx/user",
type: "form",
headers: { Authorization:"Basicb3JkZXItc2VydmVyOjEyMzQ1Ng==" },
data: {}
}).then(function(res) {
let expires_time =
new Date().getTime() +
parseInt(res.data.token.expires_in * 0.8) * 1000;
let token = res.data.token;
token.expires_time = expires_time;
localStorage.setItem("token", JSON.stringify(token));
}).catch(function(err) {
console.log(err);
});
//退出清空token
this.http({
method: "get",
url: "/xxxxx/logout",
data: {}
}).then(function(res) {
localStorage.removeItem("token");
}).catch(function(err) {
console.log(err);
});
總結(jié)
以上所述是小編給大家介紹的vue下axios攔截器token刷新機制的實例代碼,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關(guān)文章
Vue3.2?新增指令?v-memo?用法詳解(提高性能利器)
v-memo 接受一個依賴的數(shù)組,依賴的數(shù)組變化,v-memo 所對應(yīng)的 DOM 包括子集將會重新渲染,這篇文章主要介紹了Vue3.2?新增指令?v-memo?用法,提高性能的又一利器,需要的朋友可以參考下2022-09-09
vue2導(dǎo)航根據(jù)路由傳值,而改變導(dǎo)航內(nèi)容的實例
下面小編就為大家?guī)硪黄獀ue2導(dǎo)航根據(jù)路由傳值,而改變導(dǎo)航內(nèi)容的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11
關(guān)于在vue-cli中使用微信自動登錄和分享的實例
本篇文章主要介紹了關(guān)于在vue-cli中使用微信自動登錄和分享的實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06

