1. 程式人生 > >基於vue和axious的http攔截和路由攔截

基於vue和axious的http攔截和路由攔截

一個專案學會vue全家桶+axios實現登入、攔截、登出功能,以及利用axios的http攔截器攔截請求和響應。

前言

該專案是利用了Github 提供的personal token作為登入token,通過token訪問你的Repository List。通過這個專案學習如何實現一個前端專案中所需要的 登入及攔截、登出、token失效的攔截及對應 axios 攔截器的使用。

準備

你需要先生成自己的 Github Personal Token(生成Token)。 Token 生成後 訪問 Demo,即可檢視你的Repository List。

專案結構

  1. .
  2. ├── README.md
  3. ├── dist // 打包構建後的資料夾
  4. │   ├── build.js
  5. │   └── build.js.map
  6. ├── index.html
  7. ├── package.json
  8. ├── src
  9. │   ├── App.vue
  10. │   ├── assets
  11. │   │   ├── css.css
  12. │   │   ├── icon.css
  13. │   │   └── logo.png
  14. │   ├── constant
  15. │   │   └── api.js // 配置api介面檔案
  16. │   ├── http.js // 封裝fetch、post請求及http 攔截器配置檔案
  17. │   ├── index.vue
  18. │   ├── login.vue
  19. │   ├── main.js
  20. │   ├── repository.vue
  21. │   ├── router.js // 路由配置檔案
  22. │   └── store
  23. │   ├── store.js
  24. │   └── types.js // vuex types
  25. └── webpack.config.js

技術棧

  • Vue 2.0
  • vue-router
  • vuex
  • axios
  • vue-material

登入攔截邏輯

第一步:路由攔截

首先在定義路由的時候就需要多新增一個自定義欄位requireAuth,用於判斷該路由的訪問是否需要登入。如果使用者已經登入,則順利進入路由, 否則就進入登入頁面。

const
routes = [ { path: '/', name: '/', component: Index }, { path: '/repository', name: 'repository', meta: { requireAuth: true, // 新增該欄位,表示進入這個路由是需要登入的 }, component: Repository }, { path: '/login', name: 'login', component: Login } ];

定義完路由後,我們主要是利用vue-router提供的鉤子函式beforeEach()對路由進行判斷。

router.beforeEach((to, from, next) => {
    if (to.meta.requireAuth) {  // 判斷該路由是否需要登入許可權
        if (store.state.token) {  // 通過vuex state獲取當前的token是否存在
            next();
        }
        else {
            next({
                path: '/login',
                query: {redirect: to.fullPath}  // 將跳轉的路由path作為引數,登入成功後跳轉到該路由
            })
        }
    }
    else {
        next();
    }
})

每個鉤子方法接收三個引數:

  • to: Route: 即將要進入的目標 路由物件
  • from: Route: 當前導航正要離開的路由
  • next: Function: 一定要呼叫該方法來 resolve 這個鉤子。執行效果依賴 next 方法的呼叫引數。
    • next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。
    • next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了(可能是使用者手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。
    • next(‘/’) 或者 next({ path: ‘/’ }): 跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。


確保要呼叫 next 方法,否則鉤子就不會被 resolved。

完整的方法見/src/router.js

其中,to.meta中是我們自定義的資料,其中就包括我們剛剛定義的requireAuth欄位。通過這個欄位來判斷該路由是否需要登入許可權。需要的話,同時當前應用不存在token,則跳轉到登入頁面,進行登入。登入成功後跳轉到目標路由。

登入攔截到這裡就結束了嗎?並沒有。這種方式只是簡單的前端路由控制,並不能真正阻止使用者訪問需要登入許可權的路由。還有一種情況便是:當前token失效了,但是token依然儲存在本地。這時候你去訪問需要登入許可權的路由時,實際上應該讓使用者重新登入。 這時候就需要結合 http 攔截器 + 後端介面返回的http 狀態碼來判斷。

第二步:攔截器

要想統一處理所有http請求和響應,就得用上 axios 的攔截器。通過配置http response inteceptor,當後端介面返回401 Unauthorized(未授權),讓使用者重新登入。

// http request 攔截器
axios.interceptors.request.use(
    config => {
        if (store.state.token) {  // 判斷是否存在token,如果存在的話,則每個http header都加上token
            config.headers.Authorization = `token ${store.state.token}`;
        }
        return config;
    },
    err => {
        return Promise.reject(err);
    });

// http response 攔截器
axios.interceptors.response.use(
    response => {
        return response;
    },
    error => {
        if (error.response) {
            switch (error.response.status) {
                case 401:
                    // 返回 401 清除token資訊並跳轉到登入頁面
                    store.commit(types.LOGOUT);
                    router.replace({
                        path: 'login',
                        query: {redirect: router.currentRoute.fullPath}
                    })
            }
        }
        return Promise.reject(error.response.data)   // 返回介面返回的錯誤資訊
    });

完整的方法見/src/http.js.

通過上面這兩步,就可以在前端實現登入攔截了。登出功能也就很簡單,只需要把當前token清除,再跳轉到首頁即可。

原始碼位置 https://github.com/superman66/vue-axios-github