目前手頭的vue項目關(guān)于權(quán)限一塊有一個需求,其實架構(gòu)師很早就要求我做了,但是由于這個緊急程度不是很高,最近臨近項目上線,我才想起,于是趕緊補(bǔ)上這個功能。這個項目是基于OAuth2.0認(rèn)證,需要在每個請求的頭部攜帶access_token,如果這個access_token過期,需要利用已有的refresh
          _token去重新獲取一個access_token,如果連這個refresh_token也過期了,那就是真正的過期了,需要退出登錄頁面。refresh_token在獲取新的access_token的時候需要讓用戶無感知,也叫無痛刷新。

            這里的代碼實現(xiàn)肯定是要在axios攔截器里寫的,但是是在請求攔截器里寫還是在響應(yīng)攔截器里寫還是有區(qū)別的:


            1.寫在請求攔截器里:每次請求之前都會先請求一個checkToken的接口,來確認(rèn)這個access_token是否過期,如果沒有過期,直接就發(fā)起原本的請求,如果過期,利用已有的refresh
          _token去重新獲取一個access_token之后,再發(fā)起原本的請求。但是這樣寫有個缺點,就是每次請求之前都要額外請求一次checkToken的接口,如果網(wǎng)速不好,會給用戶造成不好的體驗,而且對服務(wù)器造成了性能上的浪費。

            2.寫在響應(yīng)攔截器里:直到access_token過期,返回401未授權(quán),才利用已有的refresh _token去重新獲取一個access_token。

            最后我和后端討論了下,最后采用了第二種方法,把checkToken放在后端,前端無感知刷新寫在響應(yīng)攔截器里。

          這里寫的一個響應(yīng)攔截器:
          import axios from 'axios' //創(chuàng)建一個axios實例 const service = axios.create({ timeout:
          5000,// 請求超時時間 withCredentials:true //表示跨域請求時是否需要使用憑證. 默認(rèn)為false }) var loading;
          //遮罩層 // 響應(yīng)攔截器
          service.interceptors.response.use( response => { //do what you like }, error
          => { loading.close(); if (error && error.response) { switch
          (error.response.status) {case 400: error.message = '請求錯誤' break case 401: return
          doRequest(error);case 403: error.message = '拒絕訪問' break case 404: error.message
          = `請求地址出錯: ${error.response.config.url}` break case 408: error.message = '請求超時'
          break case 500: error.message = '服務(wù)器內(nèi)部錯誤' break case 501: error.message =
          '服務(wù)未實現(xiàn)'break case 502: error.message = '網(wǎng)關(guān)錯誤' break case 503: error.message =
          '服務(wù)不可用'break case 504: error.message = '網(wǎng)關(guān)超時' break case 505: error.message =
          'HTTP版本不受支持'break default: break } } errorLog(error) return
          Promise.reject(error) } )

          ? export?default?service ?
            可以看到在響應(yīng)攔截器的錯誤回調(diào)函數(shù)里401值的時候調(diào)用了一個方法doRequest();
          async function doRequest (error) { try { const data = await getNewToken(); var
          token=data.data.token_type+' '+data.data.access_token; sessionStorage.setItem(
          'RequestToken',token); const res = await service.request(error.config) return
          res; }catch(err) { Message({ message: '登錄會話已過期,請重新登錄', type: 'error', duration:
          5 * 1000 }) sessionStorage.clear(); router.replace({ path:"/login" }); return
          err; } }
            這里的重點這些請求必須是同步的,同步的,同步
          的,重要的事情說三遍,而axios默認(rèn)是異步的,所以你要么使用ES6的async/await語句,要么使用then回調(diào)函數(shù),必須保持是同步的。而getNewToken()則是利用refresh_token重新獲取access_token方法。算了,一并貼出,僅作參考。
          import qs from 'qs' async function getNewToken() { var
          refreshToken=sessionStorage.getItem('refreshToken'); return await axios({ url:
          '/OAuth/oauth/token', method: 'post', headers: { 'Authorization': 'Basic
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
          'Content-Type':'application/x-www-form-urlencoded' }, data:qs.stringify({
          grant_type:'refresh_token', refresh_token : refreshToken }) }) }
            下面看效果。為了效果,這里設(shè)置了access_token有效時間為5s,refresh _token有效時間為10s。動圖是這樣的:



            一步一步分解下,登錄的時候,獲取到access_token和refresh
          _token。然后帶著access_token:f0a3******cb64去訪問menuQuery接口是可以正常請求的。



          ?  但是之后,我等了超過5s后(不超過10s,這個時候access_token已過期,refresh
          _token未過期)發(fā)了一個對0304接口的請求,這個時候返回401未授權(quán),說明access_token:f0a3******cb64已過期。



          ?  這時利用refresh_token重新獲取access_token。




            可以看到返回了一個新的access_token:8332******1c8a,于是帶著這個新的access_token重新發(fā)起對0304接口的請求,這個時候就可以返回所需要的數(shù)據(jù)。

          ?

          ?

            之后再等超過5s,這個時候access_token過期了,refresh _token也過期了。動圖是這樣的:



          ?

            ?這時的請求返回的是400,而不是401了,這說明refresh _token:826b******17d1過期了。這個時候就該退出登錄界面,重新登錄了。



          ?  最后,放一個總的效果圖:


          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務(wù)器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點信息
          問題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                日本少妇AA一级特黄大片 | 娇妻玩4p被3个男子伺候的简介 | 性色情爱一二三区A级高清视 | 日剧大尺度床戏做爰 | 三级-狂情欲事 |