前 後端分離許可權控制設計和實現思路

2021-10-07 12:00:53 字數 4002 閱讀 7095

前、後端分離許可權控制設計和實現思路

簡述近幾年隨著react、angular、vue等前端框架興起,前後端分離的架構迅速流行。但同時許可權控制也帶來了問題。

網上很多前、後端分離許可權僅僅都僅僅在描述前端許可權控制、且是較簡單、固定的角色場景,滿足不了我們使用者、角色都是動態的場景。且僅僅前端進行許可權控制並不是真正意義的許可權控制,它只是減少頁面結構暴露、增強使用者體驗的功效。

場景系統為後台管理系統,包含了使用者建立、使用者登入、使用者管理自己的資源。使用者經常會新增、刪除,也可以根據工作情況隨時調整頁面、功能許可權,所以採用使用者-角色-頁面許可權方案實現。

為什麼不行:

根據前端路由表顯示左側選單,但vue-router的路由表主要為了組織**,經常我們所需要的選單並非一致。比如某個前端路由a子路由有b、c,但選單中我們想要直接一級選單就顯示b、c或者將b、c各放到其他選單下。所以這種非常不靈活。

乙個路由是選單還是頁面?是否需要顯示到選單中?是否驗證許可權?哪個角色或者使用者擁有許可權?這些都需要寫到前端路由裡面,一旦有任何許可權變動就要大量調整**。

如果許可權寫死在前端,那麼角色或者使用者必須已知且固定不變。比如頁面1的meta增加屬性標識可訪問的角色為a和b

頁面乙個頁面即乙個前端頁面,比如首頁、使用者管理頁、資源管理頁等。

基本思路為:前端路由保持不變,資料庫儲存選單結構、頁面許可權控制(可以直接做成乙個頁面來方便管理)等,前端根據資料庫中的選單結構和許可權資訊來渲染乙個選單出來並只顯示其有許可權的選單,並在路由守衛中進行許可權控制防止手動輸入path越權開啟頁面

1、前端路由(vue-router)中需要正常建立頁面及路由。

2、資料庫儲存選單結構和頁面許可權資訊,

選單(目錄、非內容頁)可以自己建立,不必要求前端路由中有,因為這是指選單的視覺化的組織結構

頁面(內容頁)必須是前端路由中已有頁面,因為這是使用者需要訪問的內容。

選單和頁面組成上下級關係,一級可以是選單也可以是內容頁,內容頁也可以放在選單下,不可見的內容頁也可以放在乙個普通內容頁下,這樣理論(需要頁面選單樣式支援)可以組成無限級選單。麵包屑導航也根據此層級遞迴查詢得到。

選單和頁面的基本屬性包括title(對應路由title)、name(對應路由name)、path(對應路由path)、父級、型別(選單/頁面)、是否可見(左側選單欄是否顯示:部分頁面可能是頁面內的鏈結進去)、是否需要驗證許可權(部分頁面比如首頁無需驗證許可權大家都可以進入)

不需要控制許可權且不需要顯示到左側選單的路由這裡可以不進行管理,比如404頁面等

3、前台開啟後獲取獲取資料庫的所有選單、頁面及結構,根據是否登入、是否需要驗證許可權等進行控制,或無許可權跳轉至登入頁

4、使用者登入成功後,再獲取使用者對應的的頁面許可權列表,使用上一步獲得的所有頁面、結構和使用者擁有許可權的列表渲染出乙個選單,只包含此使用者擁有許可權的,提公升使用者體檢,避免顯示大量使用者不能訪問的選單影響使用和不必要的功能暴露。

5、路由守衛中根據上一步獲得的許可權列表判斷每個跳轉,無許可權可返回404或無許可權頁面,防止使用者手動輸入path越權訪問

頁面管理:

前、後端分離許可權控制設計和實現思路

前、後端分離許可權控制設計和實現思路

功能部分功能有事需要單獨控制許可權,比如使用者管理頁面可能允許多個角色檢視,但是其中的"建立使用者"功能只允許某乙個角色使用,那麼僅僅使用頁面許可權是不夠。所以需要細粒度的功能許可權控制。

網上的方案都是說:根據資源控制增、刪、改、查等等,比如針對使用者就是使用者的建立、修改、刪除、查詢等。但是在我的實際使用中發現並不切合實際,最起碼對像我這種管理後台,資源並不單純的增刪改查,可能有其他地方的其他操作中也會對此使用者資源造成影響,比如禁用、刪除角色也要禁用、刪除使用者,那麼這個許可權到底屬於角色的許可權還是屬於使用者的許可權,或者後台又改了,角色又影響了其他資源或者不再對使用者進行操作,都會影響許可權控制。

所以更合理的方法應該為將每個功能單獨進行控制並和頁面進行關聯,且不限定必須是增、刪、改、查四種,可以任意定製,只需要與前後端開發約定乙個唯一的標識即可。

如上的例子中,使用者管理頁面下有使用者各種功能,角色管理頁面中也有個角色禁用、刪除功能,可以分別定義標識為roledisable、roledelete,如果擁有roledelete許可權即可,即使沒有userdelete許可權,也可以直接刪除使用者,否則就不要給其role_delete許可權。

使用者登入後,從資料庫獲取其所擁有的的許可權列表並存入vuex,包含頁面和功能對應關係,例如頁面name為user:,頁面中根據刪除按鈕可以v-if="haspermission(『user_delete』)"判斷即可

頁面功能管理:

前、後端分離許可權控制設計和實現思路

獲取使用者擁有的許可權:

前、後端分離許可權控制設計和實現思路

角色乙個角色類似於乙個身份或崗位,每個角色有自己的許可權範圍。

乙個角色可以擁有多個頁面許可權。

乙個角色可以擁有多個功能許可權。

角色管理:

前、後端分離許可權控制設計和實現思路

角色分配許可權:

前、後端分離許可權控制設計和實現思路

使用者使用者可以建立、刪除,乙個使用者隨時可能變更工作內容,或者身兼數職,所以可以為其分配乙個或者多個角色,他擁有的角色的許可權就是他的許可權。此時已經可以打通許可權前端的許可權分配,使用者-角色-頁面許可權、功能許可權。

使用者管理:

前、後端分離許可權控制設計和實現思路

使用者分配角色:

前、後端分離許可權控制設計和實現思路

前端效果

前端頁面選單效果:

前、後端分離許可權控制設計和實現思路

後端許可權

傳統前後端不分離的情況下,路由都在後端統一管理,簡單的方法比如使用者管理頁面/user/那麼他裡面使用的介面都使用/user/add、/user/delete等相同字首,那麼只要判斷使用者擁有/user/許可權就可以訪問/user/*所有介面。

前後端分離後面臨的問題:

前、後端分別有自己的路由,且乙個頁面會同時調後端多個不同模組下的介面,這樣一來就無法通過以上傳統方式判斷許可權。

如此一來嗎,就需要有前端頁面到後端介面的管理,明確乙個頁面會呼叫哪幾個介面。這樣當授權使用者頁面時,系統就可以根據此關係推斷哪些介面具有許可權。

介面方案:

需要控制許可權的介面進行上傳管理(可以做成管理頁面)

每個頁面和功能可以關聯多個介面,比如使用者頁面關聯了使用者查詢介面和使用者編輯介面,使用者刪除功能關聯使用者刪除介面

後端對請求的路徑進行判斷,使用者->角色->頁面/功能->介面,擁有介面許可權即允許訪問

前後端分團隊開發,不容易一一對照,且前端有自己的路由(此路由受限於**組織結構)等等,無法使用傳統方式簡單處理

相同的介面可能會被前端多個頁面多次利用

介面管理:

前、後端分離許可權控制設計和實現思路

頁面關聯介面、功能關聯介面:

前、後端分離許可權控制設計和實現思路

請求的介面無許可權時:

前、後端分離許可權控制設計和實現思路

介面後端許可權控制

後端控制其實很簡單,只要前面管理功能做好即可,基本邏輯為:

使用者訪問介面

判斷使用者和當前path,根據使用者->角色->頁面/功能->介面 得到當前使用者有許可權的介面列表與當前path相比

若無許可權(某些介面只需要登入就能訪問的,比如獲取使用者姓名資訊的需要排除在外)則直接返回失敗,前端全域性捕獲後給出無許可權提示

資料庫表示例

紅色表為實體表,藍色表為關聯關係表。基本為使用者->角色->頁面/功能->後端介面

前、後端分離許可權控制設計和實現思路

總結1、使用者管理

1.使用者增刪改查

2.每個使用者分配乙個或多個角色

2、角色管理

1.角色增刪改查

2.每個角色分配乙個或多個頁面、功能授權

3、頁面管理

1.頁面增刪改查

2.標記頁面上下級結構、是否內容頁(需對應前端存在的路由頁面)、是否可見、是否控制許可權等等

3.前端選單、麵包屑等對使用者可感知的內容根據此上下級結構等進行渲染,不必受限於前端**中的路由

4.前端路由根據此許可權表進行許可權控制

4、介面許可權控制

1.介面管理錄入需要控制許可權的介面

2.將介面分別關聯到頁面、功能

3.擁有功能許可權則擁有對應介面許可權,擁有頁面許可權則擁有對應的許可權

前後端許可權控制

參考文章 關於前後端分離開發中的許可權處理問題,松哥之前寫過一篇文章和大家聊這個問題 做許可權管理,乙個核心思想就是後端做許可權控制,前端做的所有工作都只是為了提高使用者體驗,我們不能依靠前端展示或者隱藏乙個按鈕來實現許可權控制,這樣肯定是不安全的。就像使用者註冊時需要輸入郵箱位址,前端校驗之後,後...

vue樹形許可權選單 前後端分離 前端許可權控制設計

我們比較常見的就是基於角色的訪問控制,使用者通過角色與許可權進行關聯。簡單地說,乙個使用者擁有多個角色,乙個角色擁有多個許可權。這樣,就構造成 使用者 角色 許可權 的授權模型。在這種模型中,使用者與角色之間 角色與許可權之間,通常都是多對多的關係。通常在業務系統裡面的許可權控制分為選單的訪問 頁面...

前後端分離 頁面許可權驗證

前端驗證 登入後 新增登入標識 localstorage.login true inc.js 公共標頭檔案處理,沒有登入 跳轉登入 top.location.href 獲取本地絕對路徑或網域名稱訪問路徑 var href document.location.href var abspath absp...