一.概述
傳統權限管理:

類似于這樣,每新增一個人都要重新給她一些權限,是針對每個人單獨設定的,這種方法已經不適用于高效管控權限的
基于此,RBAC權限模型就誕生了,Role-Based Access control也就是基于角色的權限控制,相對于傳統模式,這套方案強調一個role角色

RBAC實作了用戶和權限點的分離,相對某個用戶設定權限,不用再去一個權限一個權限的給他單獨設定,而是直接給他設定角色即可,這樣權限的分配和設計就達到了極簡,高效,當想對用戶識訓權限時,只需要識訓角色即可
二.分配員工角色
2.1 新建角色表單
應該在點擊角色時彈出角色表單


首先新建一個彈出層dialog的組件

里面標簽體dialog的一個居中布局
注意el-row快速變為flex布局,且居中分布

然后我們中間的內容部分用到組件 ,復選框組checkbox-group,中間是我們后面的角色回圈每一項

注意這個組件接受兩個父組件傳過來的值,一個是該dialog顯示隱藏的引數,一個是當前點的這個用戶的id等資訊,我拿到了才能去給這個用戶添加角色

2.2 獲取角色串列和當前用戶角色
首先需要在父組件匯入彈出組件并應用在頁面中

然后我們首先需要傳控制當前彈出顯示隱藏的資料
在父組件data定義好一個變數

給子組件傳過來

注意我們props是多個單詞采用駝峰命名法,也就是props是支持駝峰命名的,但是在用的時候,也就是傳過來的值這里要采用首字母全小寫,連接線連接的形式
后面加一個.sync的修飾符瞬間形成了自定義事件,方便我們后面子組件點擊取消確定等修改他的值
然后我們還要定義一個userId給子組件傳過來


給角色按鈕添加點擊事件,傳參當前這一行的id
在這個事件立面展示dialog,將userid賦值即可

然后就應該在子組件這邊來操作了
之前在做這個頁面的時候,獲取過角色串列


按需匯入我們這個請求函式

然后再created鉤子發起請求
這里注意,我們這個介面默認是回傳十條資料,我們就傳進去引數20,就假裝默認為有20個角色,一般角色也不會超過很多

然后取里面的角色串列給到data

遍歷回圈我們的復選框每一項
注意這里面的label,我們element組件說的很清楚,這里label既是顯示的值,也充當我們收集的值


但是我這里只想收集id,顯示name怎么辦
他存他的,我顯示的內容用一個插值語法來代替即可

然后我們得checkbox-group也要系結一個陣列用來存盤我們選擇的一些id值
data先定義


然后我們需要將當前用戶已經系結好的一些角色權限一打開就勾選上的狀態

這里是這樣做的
還是在子組件匯入請求函式,并寫在方法內
但是我們這里不是在這里呼叫,是我們父組件一點擊角色這個事件里面來呼叫
這里不能直接用父組件傳過來的id作為引數

因為我們這個id是props接受的,一個重要概念,props賦值是異步的,所以我們要一點擊角色打開的瞬間就發起請求,這個時候沒有這個id
我們可以通過給外層函式接受一個引數,然后我們的介面函式拿這個引數作為id,要知道我們是在父組件來呼叫

給子組件打標識拿到實體,然后在點擊事件呼叫這個函式

我們每次點開會有一個閃空白的瞬間
解決思路:
其原因是因為我們定義的這個函式因為async和await所以它是一個異步函式,而我們點擊事件里面,展示為true是同步操作

所以我們應該讓方法呼叫完執行完了再去展示
那么就可以給我們的這個調取實體的函式呼叫來一個await 等待他執行完才去執行下面的

2.3 給員工分配角色
定義好保存用戶角色的介面函式

給dialog確定取消點擊事件

點擊確定給引數放進去,并且sync修飾符的自定義事件傳值關閉彈出層

點擊取消直接關閉彈出層
如此就完成了給用戶分配角色,接下來就是給角色分配權限
三.權限點管理頁面
3.1 新建權限點管理頁面
在企業服務中權限一般為:頁面訪問權限 、按鈕操作權限、api訪問權限(多見于在后端進行攔截),前端一般就前兩個
而且我們一般是先有訪問權再有按鈕操作權,連頁面都看不到何談按鈕操作

一般權限管理頁面都是tree樹形結構,但是除了tree這個組件我們還可以用table組件來做

結構就像這樣一個添加按鈕,一個表格里面四列

創建一個介面統一管理檔案,這個頁面要發起五個請求,分別是獲取權限串列,添加權限、查看權限、修改和洗掉

3.2 獲取資料轉化樹形
呼叫介面請求,賦值data,并系結到頁面渲染

這樣就渲染上去了,但是只有一級目錄

我們目前只有一級,但是我們的二級三級都是在這個串列里面的
可以看到我們的資料結構,type對應層級,二級的pid就是他的父級的id

所以這里有一個專門的解決思路,針對于我們的list資料沒有children,只有id和pid轉化為樹形結構的封裝函式
第一個引數是我們的串列,第二個引數為我們的根植,也就是pid在一級下的一個值,找到這就說明到頭了
在函式里面定義一個新陣列,對我們的串列進行回圈
第一次判斷我們的一級都會判斷成功進來,然后利用遞回還是list去找,但是根值為我們的當前一級的id,也就是去查找list里面pid等于一級id的item

所以我們可以配合這個函式直接將我們的list改變結構

還沒完,我們的table組件確實有樹形結構,他說的很清楚要加一個row-key而且必須為唯一指定值


現在就有結構了

由于我們支持兩層,一個頁面訪問權,一個按鈕權

所以這個添加操作,只有一級才可以添加

3.3 新增編輯權限彈層
只需要前四個

用dialog里面放form

創建好要收集的data

v-model系結上來

注意一下這里的switch
按理說他應該是一個Boolean,但是查看檔案可知,他也可以系結字串數字等

只不過系結其他值的時候我們需要設定兩個屬性,讓他知道什么代表開什么代表關


底部確定與取消的固定套路寫法

3.4 新增、編輯、洗掉權限點
先洗掉

通過confirm彈出提示框執行兩個成功回呼,注意returnpromise的結果,可以在后面鏈式編程繼續then接受他的成功回呼

添加
我們有兩個添加,上面是添加頁面訪問權,下面這個是添加按鈕操作權

給他們都來同一個點擊事件回呼打開剛才的dialog,通過type來判斷是頁面權還是按鈕權,還要傳進來一個id,如果是頁面權直接為0,按鈕權的pid就為當前row的id

然后校驗一些表單


當我們點擊確定就應該去保存發起請求了
首先我們還要校驗一下表單驗證

注意驗證除了平時那種用法,還可以用回呼的用法
校驗成功發起請求,請求成功呼叫message提示

編輯
獲取當前這一行的資料,進行回顯

但是點擊確定要修改一下,要判斷是編輯還是新增
直接加一個if判斷有id就是編輯,沒有id就是新增

四.給角色分配權限
4.1 分配權限彈出層

同樣是dialog,先完成下面確定取消按鈕

上面為一個樹形結構

給分配權限來一個點擊事件,里面還是通過pid和id轉為tree結構的串列函式來發起請求

但會發現有行數沒有字體

這個時候就要用到我們的tree組件第二個系結的值,它是用來定義顯示欄位的名稱

將里面的每一項添加勾選框

以及當我點擊他的父級,子級不會默認勾選上,因為我如果只想讓他有頁面權,沒有按鈕權,并不需要勾選父級,子級也能勾選上


點擊分配權限將id保存下來,不管是看你已經有的權限點,還是點擊確定保存新增洗掉的,都需要他

獲取當前用戶所擁有的權限點

但是你會發現回傳的是一個陣列并且全是這個權限的id
這個時候tree組件又有兩個屬性
node-key系結這個樹形的唯一標識

默認勾選的節點陣列

然后給他賦值,并且作為default的值即可


4.2 給角色分配權限
就是當我們點擊確定按鈕應該去發起請求
首先要收集我們勾選上的值
在tree有一個方法,回傳勾選的節點形成的陣列,又因為我們前面設定了唯一標識為id,所以這個陣列就是id形成的

我們的介面剛好需要權限點的id和當前這個角色的id
怎么來呼叫這個方法
可以通過給tree來一個ref來呼叫

這個時候可以完成權限分配了,但是還有個小bug當我們點擊確定后再次點擊會發現還是顯示的之氣默認勾選上的,那是因為我們顯示勾選上的這個陣列還沒有清空,并且我們清空是在取消這個函式里面清空

首先要知道這個取消函式不光是系結給這個取消按鈕的,還有我們的dialog close事件,也就是右上角的x

所以我們點擊確定保存之后會將show改為false,相當于執行了一下close事件
自此給員工分角色,給角色分配權限就已經完成,rbac的權限資料層完成
五.前端權限應用-頁面訪問和選單
5.1 主體思路
在我們之前回傳的權限點的資料中可以看到除了name、id、pid之外還有一個屬性 標識
這個標識可以跟我們路由模塊相關聯,意思就是該用戶有這個標識就能訪問這個路由,沒有就不能訪問

用到vue-router提供的一個方法 addRoutes
大體思路如下

5.2 新建vuex管理權限模塊
在vuex新建一個js模塊

在這里面先完成一個邏輯,匯入我們的常量路由,也就是每個人都擁有的路由比如404、登錄、首頁等等
直接讓我們的routes等于常量路由
然后我們要對這個routes做一些操作,也就是讓常量路由?你自己擁有權限的路由就等于真正的你能訪問到的路由

但是這里這么寫會有問題,我們如果用state.routes作為每次的基礎值,那么如果前面是管理員登錄,他擁有100個頁面的權限,這個時候已經給到了routes,我后面又用另一個人來登錄,他就會有管理員的基礎頁面權限,所以是不對的

應該每次用常量路由來進行一個比較

5.3 vuex篩選權限路由
之前做登錄的路由守衛做過這樣一個驗證

當我們有token,頁面不在登錄頁要獲取用戶資料之后,這個藏著改用戶所有的權限標識就在這里面
所以我們應該在這里來完成

發現沒有用戶資訊,就去獲取


在這個actions里面就能拿到我們的標識,怎么和路由進行比對,我們每個路由都設定的有name,和name比較即可

然后我們需要在剛才的vuex新增的模塊來一個actions篩選權限路由
我們這里異步路由是這樣設定的,因為分了模塊化


在這個篩選函式里面第一個引數context,第二個引數就是傳進來的menus,直接對他來一個遍歷,每一個item就是標識

匯入異步路由,在遍歷里面讓他所擁有的的每一個權限的標識去和異步路由name做一個filter,這個方法會回傳一個篩選完的陣列
我們陣列不能push陣列,所以可以先給他解開

然后將篩選出的路由給到mutations,也就是會賦值給state

這里commit是為了給到state也就是為了左側的選單的一個顯示,而return是為了后面addRoutes這個方法,它是為了我們的url的一個路由顯示
5.4 權限攔截出呼叫篩選權限action
現在回到我們剛才所說的應該在路由守衛的那個位置來dispatch我們的篩選路由

還沒完,我們還要發引數,在我們上面獲取用戶資訊的函式,專門return了一個回傳值

拿到回傳值,傳引數
這里為什么后面這個也要接識訓傳值

別忘了,我們的這個actions也定義了一個routes的return

這里有一個注意點,如果這里呼叫addRoutes那就必須用next(to.path)不能直接用next()
這是vue-router的一個bug

5.5 常量和異步理由解除合并


現在url訪問自己有權限的能訪問

沒有權限的為404


但是現在左側選單欄還沒有顯示出來
原因是因為這個模板左側選單遍歷的是路由表中的路由

因為我們的addroutes并不是動態變化的,我們說的commit是給左側選單用的,這時候就發揮用場了
創建一個getters

直接匯入
并且將我們之前的洗掉

六.登出重置路由權限和404問題
首先是我們點擊退出登錄還會有問題,就是這個時候可以看到我們的state里面的routes還為上一個用戶的權限路由,并且我在url去輸入對應的路由還可以進入

這是因為我們一直在addRoutes而沒有在登出去重置或者洗掉他
在我們的vuerouter檔案里面可以看到一個函式,這個是重置路由的函式

那么我們應該在登出的vuex里面呼叫一下這個方法


然后第二部操作應該將state里面的routes為初始狀態
我們應該呼叫這個mutations,然后傳進去的引數為空陣列

問題來了,我們這里是在一個vuex里面要去commit兄弟級別的vuex里面這個怎么來做

子模塊呼叫子模塊,兩種情況,一種是都沒加鎖的情況都沒有命名空間的情況,那就可以直接呼叫,因為都默認是在全域配置下的
第二種是都加了命名空間的情況,我們的commit包括dispatch其實是有第三個引數的,第三個引數是一個物件,如果來一個root:true,表示呼叫根級的子模塊

解決第二個問題
當我們一重繪就會出現404
看到我們的router組態檔,有一個404的重定向路由,他有一個宣告說的必須放到最后,這里我們由于把她放進了常量路由,又加了一些vuex里面的路由再加上異步路由導致他雖然這里是在最后,但其實已經沒有在最后的位置了

所以我們應該把這一段洗掉,然后添加在我們addRoutes這里

七.功能權限應用
7.1 功能權限的受控思路
前面我們完成了頁面的訪問權,但是該頁面中某些功能用戶可能有也可能沒有,這就是功能受限
也是在我們userInfo資料里面的points這個屬性里面

就是我們權限管理下頁面權限下

這就表示有新增的按鈕權限


就是讓有這個權限的按鈕顯示,沒有就隱藏
7.2 使用mixin技術將檢查方法注入
定義規則

全域混入

然后那個按鈕有權限就呼叫這個方法,引數為這個按鈕的權限標識


當然你直接是想連看都看不到

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/540906.html
標籤:其他
上一篇:JS如何回傳異步呼叫的結果?
