1.在開發過程當中,咱們都會接觸到token,token的做用是什麼呢?主要的做用就是爲了安全,用戶登錄時,服務器會隨機生成一個有時效性的token,用戶的每一次請求都須要攜帶上token,證實其請求的合法性,服務器會驗證token,只有經過驗證纔會返回請求結果。ios
2.當token失效時,如今的網站通常會作兩種處理,一種是跳轉到登錄頁面讓用戶從新登錄獲取新的token,另一種就是當檢測到請求失效時,網站自動去請求新的token,第二種方式在app保持登錄狀態上面用得比較多。axios
3.下面進入主題,咱們請求用的是axios,無論用何種請求方式,刷新token的原理都是同樣的。安全
//封裝了一個統一的請求函數,這個不是重點服務器
export default function request(url, options) { const token = localStorage.getItem('token'); const defaultOptions = { headers: { Authorization: `Bearer ${token}`, }, withCredentials: true, url: url, baseURL: BASE_URL, }; const newOptions = { ...options, ...defaultOptions }; return axios.request(newOptions) .then(checkStatus) .catch(error => console.log(error)); }
// 封裝了一個檢測返回結果的函數,與後臺返回狀態碼code === 1002表示token失效app
let isRefreshing = true; function checkStatus(response) { if (response && response.code === 1002) { // 刷新token的函數,這須要添加一個開關,防止重複請求 if(isRefreshing){ refreshTokenRequst() } isRefreshing = false; // 這個Promise函數很關鍵 const retryOriginalRequest = new Promise((resolve) => { addSubscriber(()=> { resolve(request(url, options)) }) }); return retryOriginalRequest; }else{ return response; } }
// 刷新token的請求函數函數
function refreshTokenRequst(){ let data; const refreshToken = localStorage.getItem('refreshToken'); data:{ authorization: 'YXBwYXBpczpaSWxhQUVJdsferTeweERmR1praHk=', refreshToken, } axios.request({ baseURL: BASE_URL, url:'/app/renewal', method: 'POST', data, }).then((response)=>{ localStorage.setItem('refreshToken',response.data.refreshToken); localStorage.setItem('token',response.data.token); onAccessTokenFetched(); isRefreshing = true; }); }
// Promise函數集合網站
let subscribers = []; function onAccessTokenFetched() { subscribers.forEach((callback)=>{ callback(); }) subscribers = []; } function addSubscriber(callback) { subscribers.push(callback) }
總結:其實token失效,自動刷新token,在頁面只有一個請求的時候是比較好處理的,可是若是頁面同時有多個請求,而且都會產生token失效,這就須要一些稍微複雜的處理,解決方式主要是用了Promise 函數來進行處理。每個token失效的請求都會存到一個Promise函數集合裏面,當刷新token的函數執行完畢後,纔會批量執行這些Promise函數,返回請求結果。還有一點要注意一下,這兒設置一個刷新token的開關isRefreshing,這個是很是有必要的,防止重複請求。url