前、后端分離權(quán)限控制設(shè)計(jì)與實(shí)現(xiàn)

來(lái)自:薛定諤的貓
鏈接:https://www.yuque.com/zhanghaofei/blog/xrpz9p

簡(jiǎn)述

近幾年隨著react寝姿、angular交排、vue等前端框架興起,前后端分離的架構(gòu)迅速流行饵筑。但同時(shí)權(quán)限控制也帶來(lái)了問(wèn)題埃篓。

網(wǎng)上很多前、后端分離權(quán)限僅僅都僅僅在描述前端權(quán)限控制根资、且是較簡(jiǎn)單架专、固定的角色場(chǎng)景,滿足不了我們用戶玄帕、角色都是動(dòng)態(tài)的場(chǎng)景部脚。且僅僅前端進(jìn)行權(quán)限控制并不是真正意義的權(quán)限控制,它只是減少頁(yè)面結(jié)構(gòu)暴露桨仿、增強(qiáng)用戶體驗(yàn)的功效睛低。

場(chǎng)景

系統(tǒng)為后臺(tái)管理系統(tǒng),包含了用戶創(chuàng)建服傍、用戶登錄钱雷、用戶管理自己的資源。用戶經(jīng)常會(huì)新增吹零、刪除罩抗,也可以根據(jù)工作情況隨時(shí)調(diào)整頁(yè)面、功能權(quán)限灿椅,所以采用用戶-角色-頁(yè)面權(quán)限方案實(shí)現(xiàn)套蒂。

為什么不行:

  1. 根據(jù)前端路由表顯示左側(cè)菜單钞支,但vue-router的路由表主要為了組織代碼,經(jīng)常我們所需要的菜單并非一致操刀。比如某個(gè)前端路由a子路由有b烁挟、c,但菜單中我們想要直接一級(jí)菜單就顯示b骨坑、c或者將b撼嗓、c各放到其他菜單下。所以這種非常不靈活欢唾。

  2. 一個(gè)路由是菜單還是頁(yè)面且警?是否需要顯示到菜單中?是否驗(yàn)證權(quán)限礁遣?哪個(gè)角色或者用戶擁有權(quán)限斑芜?這些都需要寫(xiě)到前端路由里面,一旦有任何權(quán)限變動(dòng)就要大量調(diào)整代碼祟霍。

  3. 如果權(quán)限寫(xiě)死在前端杏头,那么角色或者用戶必須已知且固定不變。比如頁(yè)面1的meta增加屬性標(biāo)識(shí)可訪問(wèn)的角色為a和b

頁(yè)面

一個(gè)頁(yè)面即一個(gè)前端頁(yè)面沸呐,比如首頁(yè)大州、用戶管理頁(yè)、資源管理頁(yè)等垂谢。

基本思路為:前端路由保持不變,數(shù)據(jù)庫(kù)存儲(chǔ)菜單結(jié)構(gòu)疮茄、頁(yè)面權(quán)限控制(可以直接做成一個(gè)頁(yè)面來(lái)方便管理)等滥朱,前端根據(jù)數(shù)據(jù)庫(kù)中的菜單結(jié)構(gòu)和權(quán)限信息來(lái)渲染一個(gè)菜單出來(lái)并只顯示其有權(quán)限的菜單,并在路由守衛(wèi)中進(jìn)行權(quán)限控制防止手動(dòng)輸入path越權(quán)打開(kāi)

頁(yè)面

  1. 前端路由(vue-router)中需要正常創(chuàng)建頁(yè)面及路由力试。

  2. 數(shù)據(jù)庫(kù)存儲(chǔ)菜單結(jié)構(gòu)和頁(yè)面權(quán)限信息徙邻,

  3. 菜單(目錄、非內(nèi)容頁(yè))可以自己創(chuàng)建畸裳,不必要求前端路由中有缰犁,因?yàn)檫@是指菜單的可視化的組織結(jié)構(gòu)

  4. 頁(yè)面(內(nèi)容頁(yè))必須是前端路由中已有頁(yè)面,因?yàn)檫@是用戶需要訪問(wèn)的內(nèi)容怖糊。

  5. 菜單和頁(yè)面組成上下級(jí)關(guān)系帅容,一級(jí)可以是菜單也可以是內(nèi)容頁(yè),內(nèi)容頁(yè)也可以放在菜單下伍伤,不可見(jiàn)的內(nèi)容頁(yè)也可以放在一個(gè)普通內(nèi)容頁(yè)下并徘,這樣理論(需要頁(yè)面菜單樣式支持)可以組成無(wú)限級(jí)菜單。面包屑導(dǎo)航也根據(jù)此層級(jí)遞歸查詢得到扰魂。

  6. 菜單和頁(yè)面的基本屬性包括title(對(duì)應(yīng)路由title)麦乞、name(對(duì)應(yīng)路由name)蕴茴、path(對(duì)應(yīng)路由path)、父級(jí)姐直、類型(菜單/頁(yè)面)倦淀、是否可見(jiàn)(左側(cè)菜單欄是否顯示:部分頁(yè)面可能是頁(yè)面內(nèi)的鏈接進(jìn)去)、是否需要驗(yàn)證權(quán)限(部分頁(yè)面比如首頁(yè)無(wú)需驗(yàn)證權(quán)限大家都可以進(jìn)入)

  7. 不需要控制權(quán)限且不需要顯示到左側(cè)菜單的路由這里可以不進(jìn)行管理声畏,比如404頁(yè)面等

  8. 前臺(tái)打開(kāi)后獲取獲取數(shù)據(jù)庫(kù)的所有菜單撞叽、頁(yè)面及結(jié)構(gòu),根據(jù)是否登錄砰识、是否需要驗(yàn)證權(quán)限等進(jìn)行控制能扒,或無(wú)權(quán)限跳轉(zhuǎn)至登錄頁(yè)

  9. 用戶登錄成功后,再獲取用戶對(duì)應(yīng)的的頁(yè)面權(quán)限列表辫狼,使用上一步獲得的所有頁(yè)面初斑、結(jié)構(gòu)和用戶擁有權(quán)限的列表渲染出一個(gè)菜單,只包含此用戶擁有權(quán)限的膨处,提升用戶體檢见秤,避免顯示大量用戶不能訪問(wèn)的菜單影響使用和不必要的功能暴露。

  10. 路由守衛(wèi)中根據(jù)上一步獲得的權(quán)限列表判斷每個(gè)跳轉(zhuǎn)真椿,無(wú)權(quán)限可返回404或無(wú)權(quán)限頁(yè)面鹃答,防止用戶手動(dòng)輸入path越權(quán)訪問(wèn)

頁(yè)面管理:

image

頁(yè)面編輯:

image

功能

部分功能有事需要單獨(dú)控制權(quán)限,比如用戶管理頁(yè)面可能允許多個(gè)角色查看突硝,但是其中的“創(chuàng)建用戶”功能只允許某一個(gè)角色使用测摔,那么僅僅使用頁(yè)面權(quán)限是不夠。所以需要細(xì)粒度的功能權(quán)限控制解恰。

網(wǎng)上的方案都是說(shuō):根據(jù)資源控制增锋八、刪、改护盈、查等等挟纱,比如針對(duì)用戶就是用戶的創(chuàng)建、修改腐宋、刪除紊服、查詢等。但是在我的實(shí)際使用中發(fā)現(xiàn)并不切合實(shí)際胸竞,最起碼對(duì)像我這種管理后臺(tái)欺嗤,資源并不單純的增刪改查,可能有其他地方的其他操作中也會(huì)對(duì)此用戶資源造成影響卫枝,比如禁用剂府、刪除角色也要禁用、刪除用戶剃盾,那么這個(gè)權(quán)限到底屬于角色的權(quán)限還是屬于用戶的權(quán)限腺占,或者后臺(tái)又改了淤袜,角色又影響了其他資源或者不再對(duì)用戶進(jìn)行操作,都會(huì)影響權(quán)限控制。

所以更合理的方法應(yīng)該為將每個(gè)功能單獨(dú)進(jìn)行控制并和頁(yè)面進(jìn)行關(guān)聯(lián),且不限定必須是增蜕便、刪叉寂、改鹅搪、查四種,可以任意定制,只需要與前后端開(kāi)發(fā)約定一個(gè)唯一的標(biāo)識(shí)即可。

如上的例子中读慎,用戶管理頁(yè)面下有用戶各種功能,角色管理頁(yè)面中也有個(gè)角色禁用槐雾、刪除功能夭委,可以分別定義標(biāo)識(shí)為role_disable、role_delete募强,如果擁有role_delete權(quán)限即可株灸,即使沒(méi)有user_delete權(quán)限,也可以直接刪除用戶擎值,否則就不要給其role_delete權(quán)限慌烧。

用戶登錄后,從數(shù)據(jù)庫(kù)獲取其所擁有的的權(quán)限列表并存入vuex鸠儿,包含頁(yè)面和功能對(duì)應(yīng)關(guān)系屹蚊,例如頁(yè)面name為user:{user: ['user_delete', 'user_query']},頁(yè)面中根據(jù)刪除按鈕可以v-if="hasPermission('user_delete')"判斷即可

頁(yè)面功能管理:

image

獲取用戶擁有的權(quán)限:

image

角色

一個(gè)角色類似于一個(gè)身份或崗位进每,每個(gè)角色有自己的權(quán)限范圍淑翼。

  1. 一個(gè)角色可以擁有多個(gè)頁(yè)面權(quán)限。

  2. 一個(gè)角色可以擁有多個(gè)功能權(quán)限品追。

角色管理:

image

角色分配權(quán)限:

image

用戶

用戶可以創(chuàng)建、刪除冯丙,一個(gè)用戶隨時(shí)可能變更工作內(nèi)容肉瓦,或者身兼數(shù)職,所以可以為其分配一個(gè)或者多個(gè)角色胃惜,他擁有的角色的權(quán)限就是他的權(quán)限泞莉。此時(shí)已經(jīng)可以打通權(quán)限前端的權(quán)限分配,用戶-角色-頁(yè)面權(quán)限船殉、功能權(quán)限鲫趁。

用戶管理:

image

用戶分配角色:

image

前端效果

前端頁(yè)面菜單效果:

image

后端權(quán)限

傳統(tǒng)前后端不分離的情況下,路由都在后端統(tǒng)一管理利虫,簡(jiǎn)單的方法比如用戶管理頁(yè)面/user/那么他里面使用的接口都使用/user/add挨厚、/user/delete等相同前綴堡僻,那么只要判斷用戶擁有/user/權(quán)限就可以訪問(wèn)/user/*所有接口。

前后端分離后面臨的問(wèn)題:

接口

方案:

  1. 需要控制權(quán)限的接口進(jìn)行上傳管理(可以做成管理頁(yè)面)

  2. 每個(gè)頁(yè)面和功能可以關(guān)聯(lián)多個(gè)接口疫剃,比如用戶頁(yè)面關(guān)聯(lián)了用戶查詢接口和用戶編輯接口钉疫,用戶刪除功能關(guān)聯(lián)用戶刪除接口

  3. 后端對(duì)請(qǐng)求的路徑進(jìn)行判斷,用戶->角色->頁(yè)面/功能->接口巢价,擁有接口權(quán)限即允許訪問(wèn)

  4. 前后端分團(tuán)隊(duì)開(kāi)發(fā)牲阁,不容易一一對(duì)照,且前端有自己的路由(此路由受限于代碼組織結(jié)構(gòu))等等壤躲,無(wú)法使用傳統(tǒng)方式簡(jiǎn)單處理

  5. 相同的接口可能會(huì)被前端多個(gè)頁(yè)面多次利用

接口管理:

image

頁(yè)面關(guān)聯(lián)接口城菊、功能關(guān)聯(lián)接口:

image

請(qǐng)求的接口無(wú)權(quán)限時(shí):

image

接口后端權(quán)限控制

后端控制其實(shí)很簡(jiǎn)單,只要前面管理功能做好即可碉克,基本邏輯為:

  1. 用戶訪問(wèn)接口

  2. 判斷用戶和當(dāng)前path凌唬,根據(jù)用戶->角色->頁(yè)面/功能->接口 得到當(dāng)前用戶有權(quán)限的接口列表與當(dāng)前path相比

  3. 若無(wú)權(quán)限(某些接口只需要登錄就能訪問(wèn)的,比如獲取用戶姓名信息的需要排除在外)則直接返回失敗棉胀,前端全局捕獲后給出無(wú)權(quán)限提示

總結(jié)

  1. 用戶管理

  2. 用戶增刪改查

  3. 每個(gè)用戶分配一個(gè)或多個(gè)角色

  4. 角色管理

  5. 角色增刪改查

  6. 每個(gè)角色分配一個(gè)或多個(gè)頁(yè)面法瑟、功能授權(quán)

  7. 頁(yè)面管理

  8. 頁(yè)面增刪改查

  9. 標(biāo)記頁(yè)面上下級(jí)結(jié)構(gòu)、是否內(nèi)容頁(yè)(需對(duì)應(yīng)前端存在的路由頁(yè)面)唁奢、是否可見(jiàn)霎挟、是否控制權(quán)限等等

  10. 前端菜單、面包屑等對(duì)用戶可感知的內(nèi)容根據(jù)此上下級(jí)結(jié)構(gòu)等進(jìn)行渲染麻掸,不必受限于前端代碼中的路由

  11. 前端路由根據(jù)此權(quán)限表進(jìn)行權(quán)限控制

  12. 接口權(quán)限控制

  13. 接口管理錄入需要控制權(quán)限的接口

  14. 將接口分別關(guān)聯(lián)到頁(yè)面酥夭、功能

  15. 擁有功能權(quán)限則擁有對(duì)應(yīng)接口權(quán)限,擁有頁(yè)面權(quán)限則擁有對(duì)應(yīng)的權(quán)限

  16. 只要通過(guò)任意頁(yè)面和功能擁有接口的權(quán)限則可以訪問(wèn)此接口

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末脊奋,一起剝皮案震驚了整個(gè)濱河市熬北,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌诚隙,老刑警劉巖讶隐,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異久又,居然都是意外死亡巫延,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)地消,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)炉峰,“玉大人,你說(shuō)我怎么就攤上這事脉执√劾” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)婆廊。 經(jīng)常有香客問(wèn)我迅细,道長(zhǎng),這世上最難降的妖魔是什么否彩? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任疯攒,我火速辦了婚禮,結(jié)果婚禮上列荔,老公的妹妹穿的比我還像新娘敬尺。我一直安慰自己,他們只是感情好贴浙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布砂吞。 她就那樣靜靜地躺著,像睡著了一般崎溃。 火紅的嫁衣襯著肌膚如雪蜻直。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天袁串,我揣著相機(jī)與錄音概而,去河邊找鬼。 笑死囱修,一個(gè)胖子當(dāng)著我的面吹牛赎瑰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播破镰,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼餐曼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了鲜漩?” 一聲冷哼從身側(cè)響起源譬,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎孕似,沒(méi)想到半個(gè)月后踩娘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喉祭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年养渴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臂拓。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖习寸,靈堂內(nèi)的尸體忽然破棺而出胶惰,到底是詐尸還是另有隱情,我是刑警寧澤霞溪,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布孵滞,位于F島的核電站中捆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏坊饶。R本人自食惡果不足惜泄伪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匿级。 院中可真熱鬧蟋滴,春花似錦、人聲如沸痘绎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)孤页。三九已至尔苦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間行施,已是汗流浹背允坚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蛾号,地道東北人稠项。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像须教,于是被迫代替她去往敵國(guó)和親皿渗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348