vue下axios攔截器token刷新機(jī)制的實(shí)例代碼
//創(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對(duì)象 function getToken() { return localStorage.getItem("token"); } //push所有請(qǐng)求到數(shù)組中 function subscribeTokenRefresh(cb) { refreshSubscribers.push(cb) } //刷新請(qǐng)求(refreshSubscribers數(shù)組中的請(qǐng)求得到新的token之后會(huì)自執(zhí)行,用新的token去請(qǐng)求數(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)已失效,請(qǐng)重新登錄。'); 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ā)起被掛起的請(qǐng)求 onRrefreshed(res.data.data.access_token) //清空數(shù)組中保存的請(qǐng)求 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是否過期,如果過期請(qǐng)求刷新token if (isTokenExpired(token)) { //判斷當(dāng)前是否正在請(qǐ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的請(qǐng)求地址,如果是直接下一步。 if (config.url.indexOf('/logined/refreshToken') === -1) { //把請(qǐng)求(token)=>{....}都push到一個(gè)數(shù)組中 let retry = new Promise((resolve, reject) => { //(token) => {...}這個(gè)函數(shù)就是回調(diào)函數(shù) subscribeTokenRefresh((token) => { config.headers.Authorization = 'Bearer ' + token //將請(qǐng)求掛起 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)用都會(huì)攜帶 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è)置請(qǐng)求超時(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刷新機(jī)制的實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
vue使用cesium創(chuàng)建數(shù)據(jù)白模方式
這篇文章主要介紹了vue使用cesium創(chuàng)建數(shù)據(jù)白模方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10Vue 實(shí)現(xiàn)樹形視圖數(shù)據(jù)功能
這篇文章主要介紹了Vue 實(shí)現(xiàn)樹形視圖數(shù)據(jù)功能,利用簡(jiǎn)單的樹形視圖實(shí)現(xiàn)的,在實(shí)現(xiàn)過程中熟悉了組件的遞歸使用,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧2018-05-05Vue監(jiān)聽一個(gè)數(shù)組id是否與另一個(gè)數(shù)組id相同的方法
今天小編就為大家分享一篇Vue監(jiān)聽一個(gè)數(shù)組id是否與另一個(gè)數(shù)組id相同的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-09-09Vue3 實(shí)現(xiàn)雙盒子定位Overlay的示例
這篇文章主要介紹了Vue3 實(shí)現(xiàn)雙盒子定位Overlay的示例,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下2020-12-12詳解Vue-cli3 項(xiàng)目在安卓低版本系統(tǒng)和IE上白屏問題解決
這篇文章主要介紹了Vue-cli3 項(xiàng)目在安卓低版本系統(tǒng)和 IE 上白屏問題解決,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-04-04