前后端分離開發中動態菜單的兩種實現方案


關於前后端分離開發中的權限處理問題,松哥之前寫過一篇文章和大家聊這個問題:

但是最近有小伙伴在學習微人事項目時,對動態菜單這一塊還是有疑問(即不同用戶登錄成功后會看到不同的菜單項),因此松哥打算再來寫一篇文章和大家聊一聊前后端分離開發中的動態菜單問題。

1. 一個原則

做權限管理,一個核心思想就是后端做權限控制,前端做的所有工作都只是為了提高用戶體驗,我們不能依靠前端展示或者隱藏一個按鈕來實現權限控制,這樣肯定是不安全的。

就像用戶注冊時需要輸入郵箱地址,前端校驗之后,后端還是要校驗,兩個校驗目的不同,前端校驗是為了提高響應速度,優化用戶體驗,后端校驗則是為了確保數據完整性。權限管理也是如此,前端按鈕的展示/隱藏都只是為了提高用戶體驗,真正的權限管理需要后端來實現。

這是非常重要的一點,做前后端分離開發中的權限管理,我們首先要建立上面這樣的思考框架,然后在這樣的框架下,去考慮其他問題。

因此,下文我會和大家分享兩種方式實現動態菜單,這兩種方式僅僅只是探討如何更好的給用戶展示菜單,而不是探討權限管理,因為權限管理是在后端完成的,也必須在后端完成。

2. 具體實現

一旦建立起這樣的思考框架,你會發現動態菜單的實現辦法太多了。

動態菜單就是用戶登錄之后看到的菜單,不用角色的用戶登錄成功之后,會看到不用的菜單項,這個動態菜單要怎么實現呢?整體來說,有兩種不同的方案,松哥曾經做過的項目中,兩種方案也都有用過,這里分別來和大家分享一下。

2.1 后端動態返回

后端動態返回,這是我在微人事中采用的方案。微人事中,權限管理相關的表一共有五張表,如下:

其中 hr 表就是用戶表,用戶登錄成功之后,可以查詢到用戶的角色,再根據用戶角色去查詢出來用戶可以操作的菜單(資源),然后把這些可以操作的資源,組織成一個 JSON 數據,返回給前端,前端再根據這個 JSON 渲染出相應的菜單。以微人事為例,我們返回的 JSON 數據格式如下:

[
    {
        "id":2,
        "path":"/home",
        "component":"Home",
        "name":"員工資料",
        "iconCls":"fa fa-user-circle-o",
        "children":[
            {
                "id":null,
                "path":"/emp/basic",
                "component":"EmpBasic",
                "name":"基本資料",
                "iconCls":null,
                "children":[

                ],
                "meta":{
                    "keepAlive":false,
                    "requireAuth":true
                }
            }
        ],
        "meta":{
            "keepAlive":false,
            "requireAuth":true
        }
    }
]

這樣的 JSON 在前端中再進行二次處理之后,就可以使用了,前端的二次處理主要是把 component 屬性的字符串值轉為對象。這一塊具體操作大家可以參考微人事項目(具體在:https://github.com/lenve/vhr/blob/master/vuehr/src/utils/utils.js),我就不再贅述了。

這種方式的一個好處是前端的判斷邏輯少一些,后端也不算復雜,就是一個 SQL 操作,前端拿到后端的返回的菜單數據,稍微處理一下就可以直接使用了。另外這種方式還有一個優勢就是可以動態配置資源-角色以及用戶-角色之間的關系,進而調整用戶可以操作的資源(菜單)。

2.2 前端動態渲染

另一種方式就是前端動態渲染,這種方式后端的工作要輕松一些,前端處理起來麻煩一些,松哥去年年末幫一個律所做的一個管理系統,因為權限上比較容易,我就采用了這種方案。

這種方式就是我直接在前端把所有頁面都在路由表里邊定義好,然后在 meta 屬性中定義每一個頁面需要哪些角色才能訪問,例如下面這樣:

[
    {
        "id":2,
        "path":"/home",
        "component":Home,
        "name":"員工資料",
        "iconCls":"fa fa-user-circle-o",
        "children":[
            {
                "id":null,
                "path":"/emp/basic",
                "component":EmpBasic,
                "name":"基本資料",
                "iconCls":null,
                "children":[

                ],
                "meta":{
                    "keepAlive":false,
                    "requireAuth":true,
                    "roles":['admin','user']
                }
            }
        ],
        "meta":{
            "keepAlive":false,
            "requireAuth":true
        }
    }
]

這樣定義表示當前登錄用戶需要具備 admin 或者 user 角色,才可以訪問 EmpBasic 組件,當然這里不是說我這樣定義了就行,這個定義只是一個標記,在項目首頁中,我會遍歷這個數組做菜單動態渲染,然后根據當前登錄用戶的角色,再結合當前組件需要的角色,來決定是否把當前組件所對應的菜單項渲染出來。

這樣的話,后端只需要在登錄成功后返回當前用戶的角色就可以了,剩下的事情則交給前端來做。不過這種方式有一個弊端就是菜單和角色的關系在前端代碼中寫死了,以后如果想要動態調整會有一些不方便,可能需要改代碼。特別是大項目,權限比較復雜的時候,調整就更麻煩了,所以這種方式我一般建議在一些簡單的項目中使用。

3. 結語

雖然我在微人事中使用了第一種方式,不過如果小伙伴是一個新項目,並且權限問題不是很復雜的話,我還是建議嘗試一下第二種方式,感覺要方便一些。

不過在公司中,動態菜單到底在前端做還是后端做,可能會有一個前后端團隊溝(si)通(bi)的過程,贏了的一方就可以少寫幾行代碼了。

關注公眾號【江南一點雨】,專注於 Spring Boot+微服務以及前后端分離等全棧技術,定期視頻教程分享,關注后回復 Java ,領取松哥為你精心准備的 Java 干貨!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM