這是大冰塊2021年第5篇原創文章,和大冰塊一塊兒在前端領域努力吧!!!💪前端
還記得在我入門沒多久的時候,第一次接觸公司中大型項目的時候,項目權限這塊把我搞的很懵。大概是個人邏輯思惟不夠強大,猛然接觸新的思惟方式總是轉不過彎來。不過功夫不負有心人,靠着前輩的指導和本身一點點摸索,總算對權限的總體流程(前端方面)有了一個基本的掌握。後端
現在回首再看,前端方面的權限管理其實沒什麼難度,就像一把鑰匙開一把鎖,只要把一一對應的邏輯關係作好就能夠了。由於思路是類似的,因此實現的代碼都是大同小異,所以本文主要以文字和邏輯圖爲主。數組
今天就來談一下 項目權限 這一塊,儘可能談的簡單一些,讓前端小白都能明白,同時也詳細說下 權限管理禁止容許 的思路,歡迎你們一塊兒討論更好的方法,也但願拋磚引玉,能有大神來指出不足與更好的改進方法。😜緩存
簡單來講,就是不一樣的用戶具備不一樣的權限:服務器
用戶A進入頁面,頁面內有
增長
,查找
兩個選項,markdown用戶B進入頁面,頁面內有
增長
,查找
,修改
,刪除
四個選項,網絡用戶C進入頁面,頁面提示
權限不足,3秒後將跳轉首頁
異步
那麼若是咱們有100個用戶,難不成要給他們搞100套權限嗎???post
固然不是,用戶並不直接對應權限,用戶對應的實際上是角色 。學習
也就是說:用戶對應角色,角色對應權限。若是咱們有一百個用戶,可是他們等級不一樣,老闆有所有的權限,經理有80%權限,組長有50%權限,職員有20%權限。
那麼其實咱們只須要4個角色:老闆角色 有所有的權限,經理角色 有80%權限,組長角色 有50%權限,職員角色 20%權限。
用戶只要對應這4個角色便可,不一樣級別的用戶就能有不一樣的權限了。
值得注意的是:
用戶和角色的對應能夠是單對多的 ,一個用戶能夠有多個角色,好比用戶小明是經理,但他可能臨時兼職一個組長,因此他對應的角色是
經理+組長
。角色和權限的對應也是單對多的 ,一個角色不必定只有一個權限,這個角色可能具備所有的權限(增刪改查等),也可能只有一部分權限(增刪)。
上面的說明能夠改爲這樣:
用戶A進入頁面,用戶A對應的角色是
職員
,全部職員
角色進入頁面,頁面內都會有增長
,查找
兩個選項,用戶B進入頁面,用戶B對應的角色是
組長
,全部組長
角色進入頁面,頁面內都會頁面內有增長
,查找
,修改
,刪除
四個選項,用戶C進入頁面,用戶C沒有對應的角色,沒有對應角色的用戶進入頁面,頁面都會提示
權限不足,3秒後將跳轉首頁
文字說明可能有不到位的地方,下面咱們來用流程圖的形式來更直觀的表現一下權限管理的邏輯。
在路由攔截中判斷當前用戶是否具備對應的頁面路由權限。
在頁面渲染前,判斷當前用戶是否具備當前頁面某功能的權限,決定是否渲染。
後端要對權限作二次鑑權處理,避免頁面渲染錯誤或者緩存問題,致使功能權限顯示,從而誤操做。
數據權限共享本質上是新加了一個臨時角色,把臨時角色加給被分享者便可。
同時,臨時角色應當記錄自身建立時間,過時時間,分享者ID以及被分享者的ID,方便後期統計溯源。
代碼實現通常是經過路由攔截與請求攔截共同實現,由於不一樣的項目代碼結構可能有所不一樣,因此以下代碼只是思路的一個延展說明,並不能直接拷貝到項目中使用哦~
// 路由攔截
// name 要前往的路由
// access 用戶權限數組
// routes 路由列表
const canTurnGo = (name, access, routes) => {
const routePermission = (list) => {
return list.some(item => {
if (item.children && item.children.length) {
return routePermission(item.children)
} else if (item.name === name) {
return hasAccess(access, item)
}
})
}
return routePermission(routes)
}
...
// 請求攔截
// 在攔截到http狀態碼非200時調用的方法
const errorHandler = function(error) {
const codeMap = {
200: '服務器成功返回請求的數據',
201: '新建或修改數據成功',
202: '一個請求已經進入後臺排隊(異步任務)',
204: '刪除數據成功',
400: '發出的請求有錯誤,服務器沒有進行新建或修改數據的操做',
401: '用戶沒有權限(令牌、用戶名、密碼錯誤)',
403: '用戶獲得受權,可是訪問是被禁止的',
404: '發出的請求針對的是不存在的記錄,服務器沒有進行操做',
406: '請求的格式不可得',
410: '請求的資源被永久刪除,且不會再獲得的',
422: '當建立一個對象時,發生一個驗證錯誤',
429: '請求次數超出當天上限',
500: '服務器發生錯誤,請檢查服務器',
502: '網關錯誤',
503: '服務不可用,服務器暫時過載或維護',
504: '網關超時',
}
const {response} = error
if (response) {
// 獲取http狀態碼對應的錯誤信息
const errorText = codeMap[response.status] || response.statusText
// 若是某個狀態碼要執行特殊操做,則:
if(status === 403){
throw new Error(errorText)
}else{
throw new Error(errorText)
}
} else {
notification.error({
description: '您的網絡發生異常,沒法鏈接服務器',
message: '網絡異常',
})
}
return
}
複製代碼
相似於這種權限管理,最重要的仍是考慮問題的思路,有了正確的思路轉化爲代碼就很容易了。
按照權限-角色-用戶
的管理方式,後期權限的維護以及增刪改查均可以放在前端來處理,後端只要配置一次就能夠再也不操做了。避免了後端代碼在權限管理的邏輯雜亂,很差維護等問題。簡單來講,每一個權限都有一個惟一的id,用戶登陸後去判斷用戶對應的角色是否對應有某權限的id,做爲判斷用戶是否具備某權限的標準。若是新增一個頁面,裏面有n個功能權限,只需把路由地址以及加入到路由權限表中,把n個功能權限添加到功能權限表中,再給角色分配對應權限便可。
這種公共的權限管理,每一個項目根據不一樣的需求都有本身的處理方式。另外,權限管理也能夠作成公共的組件,新建項目時引入配置便可,此處暫不作討論了。
這是大冰塊《看完就懂系列》的第4篇文章,《看完就懂系列》旨在把一些常見的概念或方法以通俗易懂的方式呈現出來。歡迎你們點擊其餘文章一塊兒討論學習:
原創不易,若有錯誤,歡迎指出。
若是有幫助到你,請給大冰塊來個三連(點贊收藏評論),讓咱們一塊兒在前端的路上進步吧~🤭