1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 3552字,需瀏覽 8分鐘

         ·

        2021-12-23 05:48

        點擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

        優(yōu)質(zhì)文章,第一時間送達






        -? ? ?簡述??? -

        近幾年隨著react、angular、vue等前端框架興起,前后端分離的架構(gòu)迅速流行。但同時權(quán)限控制也帶來了問題。


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



        -? ? ?場景??? -

        系統(tǒng)為后臺管理系統(tǒng),包含了用戶創(chuàng)建、用戶登錄、用戶管理自己的資源。用戶經(jīng)常會新增、刪除,也可以根據(jù)工作情況隨時調(diào)整頁面、功能權(quán)限,所以采用用戶-角色-頁面權(quán)限方案實現(xiàn)。


        為什么不行:

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

        2. 一個路由是菜單還是頁面?是否需要顯示到菜單中?是否驗證權(quán)限?哪個角色或者用戶擁有權(quán)限?這些都需要寫到前端路由里面,一旦有任何權(quán)限變動就要大量調(diào)整代碼。

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



        -? ? ?頁面??? -


        一個頁面即一個前端頁面,比如首頁、用戶管理頁、資源管理頁等。


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


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

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

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

          2. 頁面(內(nèi)容頁)必須是前端路由中已有頁面,因為這是用戶需要訪問的內(nèi)容。

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

          4. 菜單和頁面的基本屬性包括title(對應(yīng)路由title)、name(對應(yīng)路由name)、path(對應(yīng)路由path)、父級、類型(菜單/頁面)、是否可見(左側(cè)菜單欄是否顯示:部分頁面可能是頁面內(nèi)的鏈接進去)、是否需要驗證權(quán)限(部分頁面比如首頁無需驗證權(quán)限大家都可以進入)

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

        1. 前臺打開后獲取獲取數(shù)據(jù)庫的所有菜單、頁面及結(jié)構(gòu),根據(jù)是否登錄、是否需要驗證權(quán)限等進行控制,或無權(quán)限跳轉(zhuǎn)至登錄頁

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

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


        頁面管理:

        頁面編輯:




        -? ? ?功能??? -

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


        網(wǎng)上的方案都是說:根據(jù)資源控制增、刪、改、查等等,比如針對用戶就是用戶的創(chuàng)建、修改、刪除、查詢等。但是在我的實際使用中發(fā)現(xiàn)并不切合實際,最起碼對像我這種管理后臺,資源并不單純的增刪改查,可能有其他地方的其他操作中也會對此用戶資源造成影響,比如禁用、刪除角色也要禁用、刪除用戶,那么這個權(quán)限到底屬于角色的權(quán)限還是屬于用戶的權(quán)限,或者后臺又改了,角色又影響了其他資源或者不再對用戶進行操作,都會影響權(quán)限控制。


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


        如上的例子中,用戶管理頁面下有用戶各種功能,角色管理頁面中也有個角色禁用、刪除功能,可以分別定義標(biāo)識為role_disable、role_delete,如果擁有role_delete權(quán)限即可,即使沒有user_delete權(quán)限,也可以直接刪除用戶,否則就不要給其role_delete權(quán)限。


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


        頁面功能管理:

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




        -? ? ?角色??? -

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

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

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


        角色管理:

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



        -? ? ?用戶??? -

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


        用戶管理:

        用戶分配角色:



        -? ? ?前端效果??? -

        前端頁面菜單效果:





        -? ? ?后端權(quán)限??? -

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


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

        1. 前、后端分別有自己的路由,且一個頁面會同時調(diào)后端多個不同模塊下的接口,這樣一來就無法通過以上傳統(tǒng)方式判斷權(quán)限。

        如此一來嗎,就需要有前端頁面到后端接口的管理,明確一個頁面會調(diào)用哪幾個接口。這樣當(dāng)授權(quán)用戶頁面時,系統(tǒng)就可以根據(jù)此關(guān)系推斷哪些接口具有權(quán)限。




        -? ? ?接口??? -

        方案:

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

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

        1. 后端對請求的路徑進行判斷,用戶->角色->頁面/功能->接口,擁有接口權(quán)限即允許訪問

        2. 前后端分團隊開發(fā),不容易一一對照,且前端有自己的路由(此路由受限于代碼組織結(jié)構(gòu))等等,無法使用傳統(tǒng)方式簡單處理

        1. 相同的接口可能會被前端多個頁面多次利用


        接口管理:

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


        請求的接口無權(quán)限時:



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

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

        1. 用戶訪問接口

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

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



        -? ? ?數(shù)據(jù)庫表示例??? -

        紅色表為實體表,藍(lán)色表為關(guān)聯(lián)關(guān)系表?;緸橛脩?>角色->頁面/功能->后端接口



        -? ? ?總結(jié)??? -

        1. 用戶管理

          1. 用戶增刪改查

          2. 每個用戶分配一個或多個角色

        1. 角色管理

          1. 角色增刪改查

          2. 每個角色分配一個或多個頁面、功能授權(quán)

        1. 頁面管理

          1. 頁面增刪改查

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

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

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

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

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

          2. 將接口分別關(guān)聯(lián)到頁面、功能

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

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



        ? 作者?|??薛?定?諤?的?貓?

        來源 |??yuque.com/zhanghaofei/blog/xrpz9p

        加鋒哥微信:?java1239??
        圍觀鋒哥朋友圈,每天推送Java干貨!

        瀏覽 59
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日本奸妻乱伦一区二区 | 乱久久 | 男人和女人的黄色片 | 国产馆操逼的视频 | 日韩欧美国产一级 | 黄色小说哪里看 | 性video饥渴少妇china | 毛片操逼网| 超碰97手机在线观看 | 日本大香蕉天天干天天添 |