談談如何設計一個友好的權限管理模塊(上)

權限管理是很多管理系統常見的需求,說起來這是一個比較簡單的功能,但是每個人在實現的時候,往往都是以滿足自己的眼前需求爲動機,不太考慮整體的設計,導致使用不友好,拓展不方便,甚至代碼層面也是千奇百怪,使用各種方式的都有。

遙想幾年前,我還是實習生的時候,實現自己的第一個權限方面的需求,採用的是將用戶的角色存儲在localStorage裏面,然後前端代碼根據這個角色來判斷隱藏菜單欄和一些按鈕。後端壓根沒有權限表,只有角色表。

這樣的做法現在來看是很不好的,最關鍵的是相當於將權限寫死在前端了。後來,我做其他項目的時候,曾經採用前後端交互,然後前端在最開始的時候調用權限接口,然後前端再做了一大堆處理接口返回數組的邏輯。現在來看,這樣做還是有些問題,把簡單的事情複雜化。

其實,權限模塊可以做的完全動態化,可拓展,可編輯,使用友好。最關鍵的是,下次再有後端/前端兄弟和你討論如何實現權限功能,你可以按照本文介紹的大致設計告訴他,省了很多撕逼的時間。

本文前端以Vue爲例子來進行說明,後端從字段和設計表方面來說明。

首先,我們在項目裏配置好路由(這一步也可以是一部分前端提前配置,一部分取後端返回的數據渲染路由),這裏我們就全部由前端配置好了。

  {
        path: '/',
        name: 'layout',
        redirect: 'dashboard',
        component: () => import('@/views/layout/Layout'),
        children: [
            {
                path: 'dashboard',
                name: 'dashboard',
                component: () => import('@/views/dashboard/index')
            },
            {
                path: 'job',
                component: () => import('@/views/task/index'),
                children: [
                    {
                        path: '',
                        component: () => import('@/views/task/TaskList'),
                    },
                    {
                        path: 'create-task',
                        name: 'create-task',
                        component: () => import('@/views/task/TaskForm'),
                    }
                ]
            },
            {
                path: 'config',
                component: () => import('@/views/config/index'),
                children: [
                    {
                        path: 'task-type',
                        component: () => import('@/views/config/taskType/index'),
                    },
                    {
                        path: 'service',
                        component: () => import('@/views/config/serviceConfig/index'),
                    },
                    {
                        path: 'auto-scaling',
                        component: () => import('@/views/config/autoScalingConfig/index')
                    },
                    {
                        path: 'handler',
                        component: () => import('@/views/config/handlerConfig/index')
                    },
                    {
                        path: 'schedule',
                        component: () => import('@/views/config/detectConfig/index')
                    },
                    {
                        path: 'template',
                        component: () => import('@/views/config/templateConfig/index'),
                    },
                    {
                        path: 'context-keys',
                        component: () => import('@/views/config/contextKeys/index')
                    },
                    {
                        path: 'task-alert',
                        component: () => import('@/views/config/taskAlert/index')
                    }
                ]
            },
          
        ]
    },
    {
        path: '/others',
        component: () => import('@/views/others/index'),
        children: [
            {
                path: 'release',
                component: () => import('@/views/others/Release'),
            }
        ]
    },
    { path: '*', redirect: '/404', hidden: true },
    { path: '/404', component: () => import('@/views/error/404'), hidden: true },
    { path: '/401', component: () => import('@/views/error/401'), hidden: true },
    {
        path: '/login',
        component: () => import('@/views/login/index'),
        name: 'login',
    },

我們要明白,路由配置到底是前端配置好,還是取接口返回數據進行渲染,並不是很Matter的問題,因爲我們要看重的是菜單欄和用戶輸入路由進入的時候的權限。

然後,我們需要有一個菜單管理的頁面,在菜單管理頁面,新增菜單的時候,我們把菜單分爲兩部分,一部分是菜單欄的目錄和菜單,也就是頂部或者側邊展示的菜單欄;一部分是後端接口(包括前端的增刪改查按鈕,也有其他的很多接口)。這樣子就完全滿足任意的需求了,因爲後端的接口權限也在這裏直接可以編輯配置。

新增頁面的字段大概如下:

後端根據菜單排序來返回數組的順序,前端直接根據接口返回的數組渲染菜單欄。

路由地址就是前端配置好的路由裏面的path的值,前端的多語言也根據這個字段作爲詞典即可。

是否可見,我這裏的設計是因爲有些沒有子菜單的菜單,但是它也許會有子頁面(通過$router.push方法進入),我的判斷是如果它有children數組而且children的類型爲菜單的可是否見均爲false的話,就意味着在菜單欄裏它是沒有子菜單的。

功能也就是後端接口(包括前端的每個頁面的增刪改查):

上級層級就是我們新增出來的一個個目錄:

這個樹形選擇框是使用的vue-treeselect。挺好的一個vue工具。

這樣子,後端就使用一張菜單表,就可以滿足需求了。根據選擇的層級目錄ID,把它放到正確的children數組裏,不用再去搞亂七八糟的權限表,權限模塊表等等,本來問題就是這麼簡單。

菜單表的list如下:

這裏的Job就是沒有子菜單的菜單,但是它裏面是有子頁面的。

然後我們新建角色表,就可以給角色分配菜單和接口的權限了:

之後我們把角色表和具體的用戶關聯起來即可。這裏,我們既可以分配菜單,也可以分配接口,同時,頁面的具體按鈕可以根據是否勾選了接口來決定是否展示。沒有勾選的,後端不需要返回給前端。

這樣的設計即清晰明瞭,實現起來也簡單,而且完全動態化,可編輯,對管理員來說,交互也比較方便。

至此,後端的設計基本就結束了。我們完成了菜單管理,角色管理。現在前端需要考慮如何動態的渲染菜單欄,以及在用戶輸入地址的時候,如何判斷他是否可以進入。如果不可以進入,我們應該跳轉無權限頁面。

發佈了49 篇原創文章 · 獲贊 27 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章