精確到按鈕級(jí)別前端權(quán)限管理實(shí)現(xiàn)方案
這是產(chǎn)品提出的要求:
頁(yè)面上的每一個(gè)按鈕,都要可以通過(guò)角色權(quán)限來(lái)控制
當(dāng)時(shí)的項(xiàng)目背景是一個(gè)零售系統(tǒng)的后臺(tái)管理,所以會(huì)涉及到運(yùn)營(yíng)、廠家、管理員等等很多角色的使用,而其中許多數(shù)據(jù)是敏感的,例如銷量,單價(jià),利潤(rùn)等。前期的權(quán)限僅限于菜單級(jí)別的控制,也就是可以通過(guò)配置實(shí)現(xiàn)可以控制某個(gè)角色只顯示某些菜單,這也是比較常規(guī)的權(quán)限處理方案——沒(méi)權(quán)限就不讓你看那個(gè)頁(yè)面唄~
舊的按鈕權(quán)限控制:
//按鈕根據(jù)角色寫(xiě)死是否有權(quán)限,靈活性很差,修改權(quán)限需要前端改代碼,而且哪個(gè)按鈕有權(quán)限純靠閱讀代碼識(shí)別 <button disabled={role !== "admin"}>刪除</button> //大致代碼,角色為admin按鈕才可用
但目前的情況是菜單的控制在現(xiàn)有系統(tǒng)的背景下已經(jīng)略顯粗放了,比如有的人是可以看銷售頁(yè)面的,只是不允許他導(dǎo)出,又或者允許他新增一個(gè)商品,但是不允許他刪除,所以呢要求雖然有點(diǎn)高,但是這個(gè)需求無(wú)疑是合理的。做過(guò)類似系統(tǒng)的朋友都應(yīng)該了解,后管系統(tǒng)的列表類型頁(yè)面,往往是增刪改查集一體的,甚至還有導(dǎo)出、綁定、上傳之類的操作。另一個(gè)前提是,實(shí)現(xiàn)按鈕權(quán)限控制的同時(shí)之前菜單權(quán)限的控制也要保留支持。
解決方案構(gòu)思:
方案一,既然某些操作是不允許的,是否可以將操作歸類統(tǒng)一賦予角色權(quán)限呢,比如運(yùn)營(yíng)A角色無(wú)刪除類權(quán)限,運(yùn)營(yíng)B角色有新增類權(quán)限,類似來(lái)歸類實(shí)現(xiàn)管理??陕涞綄?shí)處,會(huì)發(fā)現(xiàn)操作很難歸類,刪除和修改其實(shí)是類似的,綁定解綁等操作更是無(wú)法準(zhǔn)確分類;更大的問(wèn)題是,有的角色是可以的刪除A頁(yè)面數(shù)據(jù),但是不允許刪除B頁(yè)面數(shù)據(jù)的,而且這種方式靈活度也很低,比菜單好不到哪去,所以否掉。
方案二,摒棄按鈕分類思想,給每個(gè)按鈕賦予唯一code用于控制權(quán)限,管理角色權(quán)限直接勾選該角色是否激活某個(gè)code權(quán)限即可;擬定一個(gè)鑒權(quán)函數(shù),入?yún)?shù)為code,該函數(shù)放置于每個(gè)按鈕中,鑒權(quán)函數(shù)根據(jù)code是否在后端返回的該角色擁有code列表中,來(lái)判斷返回是否具有權(quán)限,具有很高的靈活性,并且菜單也可以通過(guò)加code來(lái)實(shí)現(xiàn)同樣效果,改動(dòng)微小幾乎只用增加一個(gè)鑒權(quán)函數(shù)即可實(shí)現(xiàn)核心邏輯。
方案優(yōu)化
最終采用方案二,在實(shí)際研發(fā)中,還做了優(yōu)化:
1.將權(quán)限控制按層級(jí)分為模塊,菜單,按鈕3大層級(jí),因?yàn)楫?dāng)整個(gè)模塊都沒(méi)有權(quán)限的時(shí)候,不必再判斷按鈕權(quán)限,提高性能,菜單亦如此。
2.code實(shí)際是用英文字符來(lái)表示,增強(qiáng)可讀性,例如設(shè)備菜單是deviceMenu,而不是無(wú)意義的id。
3.實(shí)際鑒權(quán)函數(shù)入?yún)槟K,菜單,按鈕3個(gè)參數(shù),更好理解也更加符合直覺(jué),模塊下有多個(gè)菜單,菜單下有多個(gè)按鈕,也就是說(shuō)幾乎每個(gè)添加按鈕都可以取名“add”,不必?fù)?dān)心重復(fù)。
4.將列表字段當(dāng)按鈕處理,甚至可以實(shí)現(xiàn)同一列表每個(gè)字段的權(quán)限控制,例如部分敏感價(jià)格字段顯示為**(當(dāng)然安全性不高)
5.后端只需返回當(dāng)前用戶角色擁有的全部模塊,菜單,按鈕code即可
具體實(shí)現(xiàn)核心代碼
// 給菜單路由增加code標(biāo)識(shí),后續(xù)根據(jù)角色擁有菜單情況遍歷剔除無(wú)權(quán)限菜單即可 { path: 'model', name: 'DeviceModelList', code: 'device_model',// 菜單僅在原路由增加code,改動(dòng)很小 meta: { title: '設(shè)備型號(hào)', icon: 'md-menu' }, component: () => import('@/views/DeviceModelList') }
// 給按鈕增加函數(shù)鑒權(quán),此處是采用禁用點(diǎn)擊,也可以使用if直接不顯示 <Button:disabled="!checkButtonPower('device','device_list','add')">添加設(shè)備</Button>
// 鑒權(quán)函數(shù),判斷模塊和菜單就不用傳第二,三個(gè)參數(shù)即可(當(dāng)時(shí)的代碼實(shí)在是不夠優(yōu)雅?。? checkButtonPower(modelCode, menuCode, buttonCode) { let powerStatus = false //取出權(quán)限列表 const isGetPower = localStorage.getItem('userPower') const powerList = isGetPower ? base64.decryptAsObj(isGetPower) : null for (const modes of powerList) { if (!!modes.menuCode && modes.menuCode == modelCode) { for (const menus of modes.childMenu) { if (!!menus.menuCode && menus.menuCode == menuCode) { for (const buttons of menus.buttons) { if (!!buttons.code && buttons.code == buttonCode) { powerStatus = true } } } } } } return powerStatus },
至此,功能實(shí)現(xiàn),如有疑問(wèn)歡迎留言 PS:后續(xù)實(shí)現(xiàn)后發(fā)現(xiàn)Vben-admin也是用的類似的思路實(shí)現(xiàn)了細(xì)粒度的權(quán)限管理,思路沒(méi)錯(cuò)~~
更多關(guān)于按鈕級(jí)別前端權(quán)限管理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
學(xué)習(xí)筆記編寫(xiě)vue的第一個(gè)程序
這篇文章主要介紹了學(xué)習(xí)筆記vue的第一個(gè)程序,其中非常詳細(xì)的為大家講解了vue程序的創(chuàng)建步驟,有需要的朋友可以學(xué)習(xí)下,希望可以有所幫助2021-08-08微信小程序 頁(yè)面跳轉(zhuǎn)如何實(shí)現(xiàn)傳值
這篇文章主要介紹了微信小程序 頁(yè)面跳轉(zhuǎn)如何實(shí)現(xiàn)傳值的相關(guān)資料,需要的朋友可以參考下2017-04-04Javascript基礎(chǔ)知識(shí)中關(guān)于內(nèi)置對(duì)象的知識(shí)
這篇文章主要介紹了Javascript基礎(chǔ)知識(shí)中關(guān)于內(nèi)置對(duì)象的相關(guān)知識(shí)的相關(guān)資料,需要的朋友可以參考下面小編薇大家?guī)?lái)的精彩文章2021-09-09autojs繪畫(huà)實(shí)現(xiàn)六邊形示例詳解
這篇文章主要為大家介紹了autojs繪畫(huà)實(shí)現(xiàn)六邊形示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01解析JS參數(shù)parseInt('012',?16)和parseInt(012,?16)是否相等
這篇文章主要為大家介紹了parseInt('012',?16)和parseInt(012,?16)是否相等原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02