前后端分離模式已然成為現在的主流模式,鑒權方式從原始的 Session 到現在的 jwt、oauth2 等等方式,無論是哪一種方式,在前端,我們都要通過使用攔截器來實現權限認證等系列操作,我們來講講 Vue 中的路由攔截器與請求攔截器中的實現方法。
用到的組件
- vue-router
- axios
請求攔截器
首先我們創建一個文件,用來封裝 axios 的一些基礎方法或配置,我把這個文件命名為 axios.js
import axios from 'axios' import router from '../router' axios.defaults.withCredentials = true; // 設置cross跨域 並設置訪問權限 允許跨域攜帶cookie信息 axios.defaults.headers.post['Content-Type'] = 'application/json' axios.defaults.headers.put['Content-Type'] = 'application/json' // http request 攔截器 axios.interceptors.request.use( config => { return config; }, error => { return Promise.reject(error); } ); // http response 攔截器 axios.interceptors.response.use( response => { return response; }, error => { return Promise.reject(error) // 返回接口返回的錯誤信息 } ); export default function () { return axios }
http request 攔截器,即請求攔截器。
例:當你本地存在 token 時,可以在請求攔截器中將 token 追加到請求header 里,就像這樣:
// http request 攔截器 axios.interceptors.request.use( config => { let token = localStorage.getItem('token'); if (token) { config.headers.Authorization = token; } return config; } );
服務器接收到請求后,對這個 token 進行校驗,通過 token 來判定是否返回你想要的數據。
請求攔截器寫好了,那響應攔截器有什么作用呢?
假如這個時候你正在用戶中心刪除某一條數據,刪除的請求加上 token 發送給了服務端后,服務端給你返回了 401 狀態碼,表示你的 token 已經失效了,你需要重新登錄。
這時候問題來了,你不可能在每一個成功的請求里都判斷一下 狀態碼是否是 401 或 token 是否失效吧?這時候響應攔截器就該登場了。
// http response 攔截器 axios.interceptors.response.use( response => { // 未登錄或會話已過期 if ('401' === response.data.code) { // 重定向到登錄頁 router.replace({ path: '/auth/login', query: {redirect: router.currentRoute.fullPath} }) } return response; }, error => { if (500 === error.response.status) { // 服務端異常 } return Promise.reject(error) // 返回接口返回的錯誤信息 } );
以上示例代碼,在響應攔截器中,判斷了每一次服務端返回的狀態碼是否是 401,如若是的,將會重定向到登錄頁,此類場景也就是登錄狀態失效,需要用戶重新授權登錄。
這里要注意的是,這里所說的狀態碼是自定義的狀態,並非請求的 Status Code,如果服務端返回的 Status Code 不是 200,則會走到攔截器的 error 里。
路由攔截器
請求攔截器實現了,但現在還有一個問題。
在單頁面應用里,使用路由跳轉頁面,在切換頁面沒有請求的情況下,如何校驗權限呢?
路由攔截器登場,我們直接在 router.js 文件里編寫路由攔截器。
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router); const router = new Router({ mode: 'history', base: process.env.BASE_URL, routes: [ { path: '/user', name: 'user', component: () => import('@/views/User.vue'), meta: { auth: true, title: '用戶中心' } }, { path: '/auth/login', name: 'login', component: () => import('@/views/auth/Login.vue'), meta: { auth: false } } ] }); // 路由攔截器 router.beforeEach(async (to, from, next) => { if (to.matched.some(record => record.meta.auth) && to.meta.auth) { // 判斷該路由是否需要登錄權限 let token = localStorage.getItem('token'); if (token) { // 獲取當前的 token 是否存在 next() } else { // 不存在 token,需要重新認證 next({ path: '/auth/login', query: { redirect: to.fullPath } }) } } next(); }); export default router
在路由文件中添加路由攔截器,如上所寫。
在每個路由中增加 meta.auth, auth = true 代表此路由頁面需要進行權限認證后才可以訪問,否則反之。
每一次路由跳轉都會經過路由攔截器,在攔截器中根據 meta.auth 判斷是否需要鑒權。本文為了新手便於理解,去除了一些比較復雜的代碼,例如 狀態管理 Vuex。
至此,一個簡單的權限認證就做好了。在這兩種攔截器上,不局限於只使用它來做鑒權,可以利用攔截器來實現自己其他的業務邏輯。
轉載 https://www.wispx.cn/article/vue-in-the-implementation-of-routing-request-interceptors.html
