基於Vue+VueRouter+Vuex+Axios的用戶登陸態路由級和接口級攔截的原理與實現

前言

先後端分離開發、獨立部署,爲前端的開發人員提供了極大的便利,同時也帶來了新的挑戰。前端

先後端分離帶來的問題

基於前端分離帶來的問題

  1. 在路由級,模塊之間的切換、跳轉須要前端進行獨立的維護
  2. 在接口級,先後端數據交互由接口進行鏈接(異步)

這是重點:前端須要根據用戶的登陸態或角色身份進行權限控制攔截,以展現對應的功能模塊或者是展現對應的數據。vue

接下來胡哥就給小夥伴分享下在實際項目中的基於Vue+VueRouter+Vuex+Axios的用戶登陸態路由級和接口級攔截的原理與實現。ios

路由級攔截

  1. 問題思考
    • 怎麼攔截

// 藉助於VueRouter的鉤子函數beforeEach,判斷是否有權限進入,執行next()或next(false) router.beforeEach((to, from ,next) => { // next() 經過,容許進入 // next(false) 禁止,不容許進入該模塊 })vue-router

  • 攔誰vuex

    // 在VueRouter的路由配置項中,增長meta屬性,設置是否須要權限驗證的標記
       // 用戶中心路由
       {
         path: 'user',
         name: 'User',
         Component: User,
         meta: {
             // 須要權限驗證
             requireAuth: true
         }
       }
    複製代碼
  1. 實現方案npm

    • 安裝vue-routeraxios

      npm i vue-router -D
      複製代碼
    • 定義路由以及路由設置權限標誌後端

      import Vue from 'vue'
        import VueRouter from 'vue-router'
        
        Vue.use(VueRouter)
        
        const router = new VueRouter({
        	// 路由規則
        	routes: [
        		{
        			path: '/',
        			name: 'Home',
        			// 引入的模塊默認是已經引入並定義了,這裏很少描述
        			component: Home,
        			children: [
        				{
        					path: 'index',
        					name: 'Index',
        					component: Index,
        					// 定義元信息
        					meta: {
        						// 權限驗證標記 false 不進行校驗攔截
        						requireAuth: false
        					}
        				},
        				{
        					path: 'user',
        					name: 'User',
        					component: User,
        					meta: {
        						// 權限驗證標記 true 進行校驗攔截
        						requireAuth: true
        					}
        				},
        				{
        					path: 'login',
        					name: 'Login',
        					component: Login,
        					meta: {
        						// 權限驗證標記 false 不進行校驗攔截
        						requireAuth: false
        					}
        				}
        			]
        		}
        	]
        })
      複製代碼
    • 權限攔截斷定服務器

    以用戶登陸態做爲標誌,進行登陸驗證session

    const router = new VueRouter({
     		routes: [
     			// ...
     		]
     	})		
     	// 權限攔截-beforeEach路由鉤子函數
     	router.beforeEach (to, from, next) {
     		// to 目的路由對象 from 來源路由對象
     		if (to.match.some(rocode => recode.meta.requireAuth)) {
     			/**
     			* 登陸狀態-可以使用aixos進行請求,拉取服務器數據,獲取用戶登陸狀態
     			* 強烈建議在本地使用localStorage或sessionStorage和vuex共同管理用戶登陸態,避免每次進入時都拉取服務器端接口以驗證用戶是否登陸,額外消耗對服務器的請求,提高用戶體驗
     			* 若是已登陸,則更新store中存儲的loginName -- 詳細查看下面的store配置
     			* 未登陸,則直接跳轉走
     			*/ 
     			let isLogin = 已登陸 ? true : false
     			// 執行攔截斷定
     			if (!isLogin) {
     				// 跳轉到登陸模塊
     				// 處理方式一:藉助next()方法
     				next({
     					name: 'Login',
     					replace: 'true',
     					// redirectUrl 用於標記登陸後回跳的地址
     					redirectUrl: to.fullPath
     				})
     				
     				// 處理方式二:使用window.loaction.href方式,須要執行next(false)配合使用
     				window.location.href = '指定的登陸地址?redirectUrl=' + to.fullPath
     				next(false)
     			} else {
     				// 已登陸,直接進入
     				next()
     			}	 
     		} else {
     			// 不執行攔截,直接進入該路由
     			next()
     		}
     	}	
    複製代碼

接口級攔截

  1. 問題思考

    • 怎麼攔截

      藉助axios的攔截器:
        interceptors.request.use 請求攔截器
        interceptors.response.use 響應攔截器
      複製代碼
    • 攔誰

      設置特定的接口地址白名單,用因而否進行用戶登陸態權限斷定

      不是全部的接口都要進行攔截的,好比:
        	1. 發送和獲取登陸信息的接口
        	2. 發送註冊信息的接口
        	3. 其餘不須要用戶態的接口
      複製代碼
  2. 實現方案

    • 安裝axios

      npm i axios -D
      複製代碼
    • 引入axios,添加攔截器

      import axios from 'axios'
        import router from '@/router'
        // 具體數據倉庫對象store配置請往下看
        import store from '@/store'
        const $http = axios.create({
        	// 基本配置項
        })
        
        // 定義接口地址白名單
        const allowUrls = [
        	'/getUserInfo',
        	'/addUserInfo'
        ]
        
        // 請求攔截器 -- 發送請求前,判斷是否存在登陸信息
        $http.interceptors.resquest.use((config) => {
        	// config.url 是請求的URL地址
        	if (allowUrls.includes(config.url)) {
        		// 判斷是否登陸 --- 本地信息以及vuex的store信息進行斷定
        		let isLogin = locationStorage.getItem('isLogin')
        		if (!isLogin || !store.state.loginName) {
        			// 攜帶當路由地址,跳轉登陸
        			// router.currentRoute.fullPath
        		} else {
        			return config
        		}
        	} else {
        		// 不須要斷定則直接返回config配置
        		return config
        	}
        })
        
        // 響應攔截器
        $http.interceptors.response.use((res) => {
        	// 判斷是否須要驗證權限
        	if (allowUrls.includes(res.config.url)) {
        		// 判斷是否登陸 --- 本地信息、vuex的store信息以及後端服務器響應回來的是否登陸的標記
        		let isLogin = locationStorage.getItem('isLogin')
        		// 約定 code 10011 表示未登陸
        		if (!isLogin || !store.state.loginName || res.data.code === 10011) {
        			// 攜帶當路由地址,跳轉登陸
        			// router.currentRoute.fullPath
        		} else {
        			return config
        		}
        	} else {
        		return res
        	}
        })
      複製代碼

數據倉庫sotre

  1. 下載安裝vuex

    npm i vuex -D
    複製代碼
  2. 配置相關項

    import Vue from 'vue'
     import Vuex from 'vuex'
     
     Vue.use(Vuex)
     
     const store =  new Vuex.Store({
     	state: {
     		// 用戶登陸後,獲取暱稱
     		loginName: ''
     	},
     	mutations: {
     		updateLoginInfo (state, loginName) {
     			state.loginName = loginName
     		}		
     	}
     })
    複製代碼

後記

以上就是胡哥今天給你們分享的內容,喜歡的小夥伴記得收藏、轉發、點擊在看呦…

胡哥有話說,一個有技術,有情懷的胡哥!京東開放平臺首席前端攻城獅。與你一塊兒聊聊大前端,分享前端系統架構,框架實現原理,最新最高效的技術實踐!

長按掃碼關注,更帥更漂亮呦!

胡哥有話說
相關文章
相關標籤/搜索