国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Vue路由權(quán)限控制解析

瀏覽:3日期:2022-11-03 17:05:31

前言

本人在公司主要負(fù)責(zé)中后臺(tái)系統(tǒng)的開發(fā),其中路由和權(quán)限校驗(yàn)算是非常重要且最為基本的一環(huán)。實(shí)際開發(fā)項(xiàng)目中,關(guān)于登錄和路由權(quán)限的控制參照了vue-element-admin這個(gè)明星項(xiàng)目,并在此基礎(chǔ)上基于業(yè)務(wù)進(jìn)行了整合,接下來(lái)我會(huì)以這個(gè)項(xiàng)目為例,仔細(xì)地剖析整個(gè)路由和權(quán)限校驗(yàn)的過(guò)程,也算是對(duì)這個(gè)知識(shí)點(diǎn)的一些總結(jié)。

項(xiàng)目總體目錄結(jié)構(gòu)

進(jìn)入今天主題之前,我們先來(lái)梳理下整個(gè)項(xiàng)目,src目錄下的。

api: 接口請(qǐng)求 assets: 靜態(tài)資源 components: 通用組件 directive: 自定義指令 filters: 自定義過(guò)濾器 icons: 圖標(biāo) layout: 布局組件(頁(yè)面架構(gòu)核心) router: 路由配置(路由權(quán)限核心模塊) store: 狀態(tài)管理 styles: 樣式文件 utils: 工具方法 views: 頁(yè)面組件 permission.js 權(quán)限管理

對(duì)這項(xiàng)目感興趣的同學(xué)可以自行,有針對(duì)性地學(xué)習(xí),除了路由權(quán)限校驗(yàn)的功能以外,也包含了很多有意思的功能,相信能夠?qū)W到不少東西。

路由權(quán)限控制邏輯

路由處理流程圖

Vue路由權(quán)限控制解析

路由處理源碼分析

我們先找到permission.js文件,此處定義全局路由守衛(wèi),也是路由權(quán)限中非常關(guān)鍵的核心代碼。為方便大家閱讀,只摘取了跟路由相關(guān)的代碼

import router from ’./router’import store from ’./store’import { Message } from ’element-ui’import NProgress from ’nprogress’ // progress barimport ’nprogress/nprogress.css’ // progress bar styleimport { getToken } from ’@/utils/auth’ // get token from cookieNProgress.configure({ showSpinner: false }) // NProgress Configurationconst whiteList = [’/login’, ’/auth-redirect’] // 白名單配置router.beforeEach(async(to, from, next) => { // start progress bar NProgress.start() // 有token if (hasToken) { if (to.path === ’/login’) // 如果當(dāng)前路徑為/login,重定向到首頁(yè) next({ path: ’/’ }) NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939 } else { // determine whether the user has obtained his permission roles through getInfo const hasRoles = store.getters.roles && store.getters.roles.length > 0 if (hasRoles) { next() } else { try { // 獲取用戶信息 const { roles } = await store.dispatch(’user/getInfo’) // 根據(jù)用戶的角色,動(dòng)態(tài)生成路由 const accessRoutes = await store.dispatch(’permission/generateRoutes’, roles) // 動(dòng)態(tài)添加路由 (將基本的路由信息跟動(dòng)態(tài)路由進(jìn)行合并) router.addRoutes(accessRoutes) // 繼續(xù)訪問(wèn) next({ ...to, replace: true }) } catch (error) { // 刪除token await store.dispatch(’user/resetToken’) Message.error(error || ’Has Error’) // 重定向到登錄頁(yè)面 next(`/login?redirect=${to.path}`) NProgress.done() } } } } else { // 沒有token if (whiteList.indexOf(to.path) !== -1) { // 如果在白名單中,則不需要進(jìn)行任何校驗(yàn),直接放行 next() } else { // 如果不存在于白名單中,則重定向到登錄頁(yè)面. next(`/login?redirect=${to.path}`) NProgress.done() } }})router.afterEach(() => { // finish progress bar NProgress.done()})

注意到,代碼中的/login?redirect=${jto.path}, 這里的redirect參數(shù)主要是用于,在用戶登錄成功后進(jìn)行跳轉(zhuǎn)的頁(yè)面路徑。具體功能在/views/login/index.vue文件下

watch: { $route: { handler: function(route) { const query = route.query if (query) { //路由查詢參數(shù) this.redirect = query.redirect this.otherQuery = this.getOtherQuery(query) } }, immediate: true }},// methods下的:handleLogin() { // 登錄函數(shù) this.$refs.loginForm.validate(valid => { if (valid) { // 賬號(hào)密碼校驗(yàn)成功后 this.$store.dispatch(’user/login’, this.loginForm) .then(() => { // 直接跳轉(zhuǎn)到this.redirect 路徑的頁(yè)面 this.$router.push({ path: this.redirect || ’/’, query: this.otherQuery }) this.loading = false }) } else { // .. } })},

動(dòng)態(tài)路由配置

我們先來(lái)看看路由的定義,在/src/router/index.js文件下

export const constantRoutes = [ // 用來(lái)定義普通的路由配置,不需要訪問(wèn)權(quán)限的 // 路由配置對(duì)象]export const asyncRoutes = [ // 通過(guò)路由元信息meta.roles來(lái)設(shè)置訪問(wèn)權(quán)限,一般來(lái)說(shuō)是個(gè)數(shù)組 { path: ’/permission’, component: Layout, redirect: ’/permission/page’, alwaysShow: true, // will always show the root menu name: ’Permission’, meta: { title: ’Permission’, icon: ’lock’, roles: [’admin’, ’editor’] // 通過(guò)roles設(shè)置路由的權(quán)限 }, // ... }]

動(dòng)態(tài)添加路由時(shí),本質(zhì)上就是根據(jù)用戶的角色信息在asyncRoutes路由配置數(shù)組中進(jìn)行路由篩選,找到相對(duì)應(yīng)的路由,與constantRoutes合并生成最新的路由。

動(dòng)態(tài)添加路由邏輯圖

Vue路由權(quán)限控制解析

動(dòng)態(tài)路由源碼分析代碼入口: permission.js

const accessRoutes = await store.dispatch(’permission/generateRoutes’, roles)

permission/generateRoutes方法入口文件:/strore/modules/permissions.js

import { asyncRoutes, constantRoutes } from ’@/router’const state = { routes: [], addRoutes: []}const mutations = { SET_ROUTES: (state, routes) => { state.addRoutes = routes state.routes = constantRoutes.concat(routes) }}const actions = { generateRoutes({ commit }, roles) { return new Promise(resolve => { let accessedRoutes if (roles.includes(’admin’)) { // 如果包含了admin,則說(shuō)明是admin,具有所有模塊的訪問(wèn)權(quán)限 accessedRoutes = asyncRoutes || [] } else { // 如果不是管理員,則需要根據(jù)用戶角色roles和異步路由進(jìn)行篩選 accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) } // 將最終的結(jié)果存放到vuex中 commit(’SET_ROUTES’, accessedRoutes) // resolve出去 resolve(accessedRoutes) }) }}

對(duì)異步路由進(jìn)行篩選,并將最終的結(jié)果存放到vuex中,并將結(jié)果resolve出去

export function hasPermission(roles, route) { if (route.meta && route.meta.roles) { // 如果存在meta.roles // 只要meta.roles中存在與用戶角色列表中相同的值,則說(shuō)明具有訪問(wèn)權(quán)限 return roles.some(role => route.meta.roles.includes(role)) } else { // 不存在meta或者是不存在meta.roles,則說(shuō)明是通用模塊,直接放行 return true }}export function filterAsyncRoutes(routes, roles) { const res = [] routes.forEach(route => { const tmp = { ...route } if (hasPermission(roles, tmp)) { // 相對(duì)路由數(shù)組的每一項(xiàng)進(jìn)行訪問(wèn)權(quán)限的判斷 if (tmp.children) { // 如果存在children,則遞歸調(diào)用篩選函數(shù) tmp.children = filterAsyncRoutes(tmp.children, roles) } // 將處理好的路由配置放入到res中 res.push(tmp) } }) return res}

最后回到/permission.js文件中

const accessRoutes = await store.dispatch(’permission/generateRoutes’, roles)// 這里的accessRoutes就是篩選之后的路由,// 最后通過(guò)route.addRoutes將constRoutes和accessRoutes進(jìn)行合并,生成最終的訪問(wèn)路由router.addRoutes(accessRoutes)

擴(kuò)展-按鈕權(quán)限

路由權(quán)限控制基本流程已經(jīng)分析完,接下來(lái)我們也來(lái)看看項(xiàng)目里的按鈕權(quán)限控制的實(shí)現(xiàn),實(shí)現(xiàn)也比較簡(jiǎn)單。

基本用法<div v-permission='[’admin’,’editor’]'></div>import store from ’@/store’function checkPermission(el, binding) { const { value } = binding // 從store中拿到我們?cè)L問(wèn)接口后,取到用戶角色信息 const roles = store.getters && store.getters.roles if (value && value instanceof Array) { // 判斷傳入的值是不是數(shù)組,規(guī)范化傳值 if (value.length > 0) { const permissionRoles = value // 只要傳入的permissionRoles中,包含了roles其中的一個(gè)值即可,則代表有權(quán)限 const hasPermission = roles.some(role => { return permissionRoles.includes(role) }) // 沒有權(quán)限則進(jìn)行刪除,不展示。 // v-permission具體實(shí)現(xiàn)可以根據(jù)業(yè)務(wù)場(chǎng)景進(jìn)行修改 if (!hasPermission) { el.parentNode && el.parentNode.removeChild(el) } } } else { throw new Error(`need roles! Like v-permission='[’admin’,’editor’]'`) }}export default { inserted(el, binding) { checkPermission(el, binding) }, update(el, binding) { checkPermission(el, binding) }}

總結(jié)

存在token

存在用戶角色信息,則說(shuō)明該用戶的最終可訪問(wèn)的路由已經(jīng)生成,可以直接放行

不存在用戶信息

1.調(diào)用獲取用戶信息接口,獲取到用戶信息, 將用戶信息存放到vuex中

2.判斷用戶角色

如果是管理員則對(duì)所有模塊具有訪問(wèn)權(quán)限 非管理員,需要對(duì)異步路由進(jìn)行篩選,通過(guò)遍歷異步路由,并通過(guò)meta.roles與用戶信息比較,判斷用戶是否具有訪問(wèn)權(quán)限

3.將最終的可訪問(wèn)路由存放到vuex中,最后通過(guò)router.addRoutes,整合最后的路由配置列表

不存在token

如果訪問(wèn)路由在白名單下,則直接進(jìn)行訪問(wèn)

訪問(wèn)路由不存在白名單下,則重定向到登錄頁(yè)面 path: /login?redirect=/xxx,登錄成功后則跳轉(zhuǎn)到/xxx對(duì)應(yīng)的頁(yè)面

以上就是Vue路由權(quán)限控制解析的詳細(xì)內(nèi)容,更多關(guān)于Vue路由權(quán)限控制的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Vue
相關(guān)文章:
主站蜘蛛池模板: 特级一级毛片视频免费观看 | 欧美成人看片一区二区三区尤物 | 一级毛片在线视频 | 亚洲一区二区三区不卡在线播放 | 精品高清国产a毛片 | 亚州在线播放 | 国产自产21区| 在线视频第一页 | 国产女女视屏免费 | 欧美一区二区在线播放 | 国产精品久久不卡日韩美女 | 成年男女拍拍拍免费视频 | 欧美一级毛片免费播放aa | 成人午夜毛片在线看 | 欧美特黄一片aa大片免费看 | 窝窝女人体国产午夜视频 | 亚洲视频在线网站 | 亚洲jjzzjjzz在线播放 | 国产免费高清福利拍拍拍 | 成人欧美一区二区三区视频 | 亚洲乱码一区二区三区国产精品 | 日本高清在线精品一区二区三区 | 国产成人精品一区二区 | 成人毛片在线视频 | 日日干日日操日日射 | 国产一二区 | 国产ssss在线观看极品 | 久久成年片色大黄全免费网站 | 欧美日韩视频在线第一区二区三区 | 在线观看欧美亚洲日本专区 | 最新亚洲人成网站在线影院 | 一本伊大人香蕉高清在线观看 | 国产欧美一区二区 | 亚洲手机在线 | 97精品国产福利一区二区三区 | 国产精品1页 | 久久无码av三级 | 日本精品网 | 九九51精品国产免费看 | 亚洲免费天堂 | 最近手机高清中文字幕大全7 |