淺談vue后臺(tái)管理系統(tǒng)權(quán)限控制思考與實(shí)踐
前言
最近在開(kāi)發(fā)管理系統(tǒng)時(shí)遇到了任何管理系統(tǒng)都會(huì)有的需求---權(quán)限控制,之前也遇到過(guò)這種需求,但是架構(gòu)不完善導(dǎo)致的各種問(wèn)題使得后期維護(hù)非常麻煩,這一次的方案解決了之前的種種問(wèn)題,現(xiàn)做一次記錄,當(dāng)然這個(gè)架構(gòu)后期可能會(huì)有坑,不過(guò)得一步一步的嘗試才能發(fā)現(xiàn)并解決問(wèn)題。
權(quán)限控制需求
因?yàn)槭菃雾?yè)面應(yīng)用,路由交給前端來(lái)控制,對(duì)于一些需要特定權(quán)限才能查看的信息的保護(hù)變得尤為重要,如果前端不做好權(quán)限校驗(yàn),后端也一時(shí)疏忽,就可能就會(huì)導(dǎo)致數(shù)據(jù)泄露。
對(duì)于權(quán)限控制,需求大致為如下:
- 對(duì)于大模塊的限制,比如需要通過(guò)路由跳轉(zhuǎn)的模塊,這時(shí)需要進(jìn)行路由攔截
- 對(duì)于小功能的限制,比如一個(gè)按鈕,如果沒(méi)有特定權(quán)限,那么這個(gè)按鈕就不顯示
安全層面的思考
之前接手了一個(gè)管理系統(tǒng),前端是將權(quán)限列表存儲(chǔ)在storage中來(lái)實(shí)現(xiàn)長(zhǎng)久儲(chǔ)存,這種實(shí)現(xiàn)方式是很不可取的,因?yàn)閔acker可以通過(guò)手動(dòng)更改存儲(chǔ)的信息來(lái)實(shí)現(xiàn)獲取特定權(quán)限,甚至系統(tǒng)都沒(méi)有做路由攔截,如果知道模塊的路由,可以直接通過(guò)輸入路由信息來(lái)直接跳轉(zhuǎn)到特定模塊。對(duì)于一些模塊的權(quán)限,權(quán)限被管理員修改后也無(wú)法立即生效,所以對(duì)于這幾種情況做了如下思考與實(shí)踐。
權(quán)限被管理員修改后立即生效
對(duì)于這個(gè)需求,我的做法是,獲取到權(quán)限列表后,將權(quán)限信息存儲(chǔ)在 vuex store 中,并且使用getter函數(shù),對(duì)于是否可以使用該權(quán)限進(jìn)行判斷,這樣一旦權(quán)限數(shù)據(jù)更新,前端權(quán)限限制功能點(diǎn)會(huì)自動(dòng)修改,從而做到權(quán)限的實(shí)時(shí)性,大致實(shí)現(xiàn)如下:
// vuex state.js
export default {
userPrivileges: {
admin: [],
purchaser: []
}, // 用戶權(quán)限信息
}
// vuex getters.js
export default {
canIUse: state => (role, id) => state.userPrivileges[role].includes(id)
}
// 頁(yè)面具體小功能,通過(guò) mapGetters 引入 canIUse 函數(shù)
<span v-if="canIUse('admin', 9)">{{scope.row.allocation_subtotal}}</span>
這樣一來(lái),數(shù)據(jù)存儲(chǔ)在內(nèi)存中,那么權(quán)限信息就無(wú)法輕易的被修改,同時(shí)對(duì)于權(quán)限的判斷也非常簡(jiǎn)單,只需要在特定功能點(diǎn)傳入功能點(diǎn)的權(quán)限id就能判斷是否可以使用這個(gè)權(quán)限了。
但是將數(shù)據(jù)存儲(chǔ)在了內(nèi)存中也會(huì)遇到一個(gè)問(wèn)題,頁(yè)面刷新怎么辦?接下來(lái)就是講解這種情況。
刷新頁(yè)面也可以進(jìn)行權(quán)限判斷
對(duì)于大模塊的權(quán)限攔截,肯定是通過(guò)路由鉤子來(lái)進(jìn)行攔截的(這種實(shí)現(xiàn)有很多文章講解過(guò),這里不具體講解),但是通過(guò)路由鉤子進(jìn)行攔截的前提是,權(quán)限信息得提前存在。
刷新頁(yè)面會(huì)存在這種情況,頁(yè)面刷新時(shí),先執(zhí)行的路由鉤子,再執(zhí)行的組件生命周期鉤子來(lái)請(qǐng)求權(quán)限的列表,此時(shí)權(quán)限信息不存在,那么頁(yè)面跳轉(zhuǎn)到登陸頁(yè)的話,體驗(yàn)就不夠友好。
所以我的做法是,建立一個(gè)中間頁(yè),如果權(quán)限校驗(yàn)不通過(guò),那么跳轉(zhuǎn)至中間頁(yè),中間頁(yè)進(jìn)行權(quán)限的請(qǐng)求,請(qǐng)求到權(quán)限后,再判斷是否可以跳轉(zhuǎn),這樣的話,刷新頁(yè)面體驗(yàn)就比較好。大致代碼如下:
// vuex actions.js
// 通過(guò)返回一個(gè)promise,使得store更新與后續(xù)代碼變?yōu)椤巴健眻?zhí)行
export default {
getUserPrivileges({ commit }) {
return fetch.get({
url: '/currentstaff'
}).then(data => {
commit('SET_USER_PRIVILEGES_INFO', data.data)
return data.data
}).catch(e => {
})
}
}
// router.js
// 需要驗(yàn)證權(quán)限的路由
{
path: 'suppliers',
component: Suppliers,
meta: {
role: 'admin',
privilegeId: 5
}
}
function isCanUseThisModule(to, from) {
return to.matched.every(record => {
// 利用路由meta存儲(chǔ)相應(yīng)權(quán)限信息
if (record.meta.role) {
return store.getters.canIUse(record.meta.role, record.meta.privilegeId)
} else {
return true // 如果不需要權(quán)限,直接返回true
}
})
}
router.beforeEach((to, from, next) => {
if (isCanUseThisModule(to, from)) {
next() // 權(quán)限驗(yàn)證通過(guò),跳轉(zhuǎn)下一路由
} else {
next({
path: '/main/privilegeValidator' // 權(quán)限驗(yàn)證不通過(guò)時(shí)的中間頁(yè)
})
}
})
// 權(quán)限校驗(yàn)中間頁(yè)代碼示例
created() {
this.$store.dispatch('getUserPrivileges').then(data => {
for (let i = 0; i < data.admin_permissions.length; i++) {
if (this.canIUse('admin', data.admin_permissions[i])) {
this.$router.push({
path: this.routerList.find(value => value.privilegeId === data.admin_permissions[i]).linkHref
})
return
}
}
this.$router.push('/login') // 如果沒(méi)有任何權(quán)限,則跳轉(zhuǎn)登陸頁(yè)面
})
}
用戶在登陸后也可以跳轉(zhuǎn)到這個(gè)權(quán)限中間頁(yè),進(jìn)行權(quán)限判斷后再跳轉(zhuǎn)到對(duì)應(yīng)模塊。
尾聲
大致的實(shí)現(xiàn)過(guò)程就是這樣,希望對(duì)大家有所幫助,如果有暗坑還請(qǐng)指出。也希望大家多多支持腳本之家。
相關(guān)文章
vue+element樹(shù)組件 實(shí)現(xiàn)樹(shù)懶加載的過(guò)程詳解
這篇文章主要介紹了vue+element樹(shù)組件 實(shí)現(xiàn)樹(shù)懶加載的過(guò)程,本文通過(guò)圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-10-10
vue和element上傳圖片以及進(jìn)行拖拽圖片排序問(wèn)題
這篇文章主要介紹了vue和element上傳圖片以及進(jìn)行拖拽圖片排序問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
vue如何使用watch監(jiān)聽(tīng)指定數(shù)據(jù)的變化
這篇文章主要介紹了vue如何使用watch監(jiān)聽(tīng)指定數(shù)據(jù)的變化,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
VueJs與ReactJS和AngularJS的異同點(diǎn)
這篇文章主要為大家詳細(xì)介紹了VueJs與ReactJS和AngularJS的異同點(diǎn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
vue+iview tabs context-menu 彈出框修改樣式的方法
今天遇到一個(gè)需求說(shuō)頁(yè)面頂部的菜單右鍵彈出框離得有點(diǎn)遠(yuǎn),需要我們做調(diào)整,下面小編給大家分享下vue+iview tabs context-menu 彈出框修改樣式的方法,感興趣的朋友跟隨小編一起看看吧2024-06-06

