作者:朝雨憶輕塵
出處:https://www.cnblogs.com/xifengxiaoma/
權限控制方案
既然是后台權限管理系統,當然少不了權限控制啦,至於權限控制,前端方面當然就是對頁面資源的訪問和操作控制啦。
前端資源權限主要又分為兩個部分,即導航菜單的查看權限和頁面增刪改操作按鈕的操作權限。
我們的設計把頁面導航菜單和頁面操作按鈕統一存儲在菜單數據庫表中,菜單表中包含以下權限關注點。
菜單類型
菜單類型代碼頁面資源的類型。類型包括,0:目錄 1:菜單 2:按鈕'。
權限標識
權限標識即是代表此頁面資源,用來進行權限控制的唯一標識,主要是進行增刪改查的權限控制。
權限標識包括,sys:user:add:新增 sys:user:edit:編輯 sys:user:delete:刪除 sys:user:view:查看。
注:目前查看都可以通過菜單可見性進行控制,所以查看權限標識目前沒有用上,如果需要顯示無權限頁面可以使用。
菜單表結構
具體的菜單表結構如下。
-- ------------------------------------------------ -- 菜單 -- ------------------------------------------------ -- Table structure for `sys_menu` -- ------------------------------------------------ CREATE TABLE `sys_menu` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '編號', `name` varchar(50) COMMENT '菜單名稱', `parent_id` bigint COMMENT '父菜單ID,一級菜單為0', `url` varchar(200) COMMENT '菜單URL', `perms` varchar(500) COMMENT '授權(多個用逗號分隔,如:sys:user:add,sys:user:edit)', `type` int COMMENT '類型 0:目錄 1:菜單 2:按鈕', `icon` varchar(50) COMMENT '菜單圖標', `order_num` int COMMENT '排序', `create_by` varchar(50) COMMENT '創建人', `create_time` datetime COMMENT '創建時間', `last_update_by` varchar(50) COMMENT '更新人', `last_update_time` datetime COMMENT '更新時間', `del_flag` tinyint DEFAULT 0 COMMENT '是否刪除 -1:已刪除 0:正常', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='菜單管理';
導航菜單實現思路
1.用戶登錄系統
用戶登錄系統之后,跳轉到首頁。
2.根據用戶加載導航菜單
在路由導航守衛路由時加載用戶導航菜單並存儲到store。
加載過程如下,返回結果排除按鈕類型。
user -> user_role -> role -> role_menu -> menu。
3.導航欄讀取菜單樹
導航欄到sotre讀取導航樹並進行展示。
頁面按鈕實現思路
1.用戶登錄系統
用戶登錄系統之后,跳轉到首頁。
2.根據用戶加載權限標識集合
在路由導航守衛路由時加載用戶權限標識集合。
加載過程如下,返回結果是用戶權限標識的集合。
user -> user_role -> role -> role_menu -> menu。
3.頁面按鈕控制
頁面操作按鈕提供權限標識,查詢是否在用戶權限標識集合中。
在:有權限,可見或可用,不在:無權限,不可見或禁用。
目前本系統采用的是狀態禁用。
權限控制實現
導航菜單權限
加載導航菜單
如下圖所示,在導航守衛路由時加載導航菜單並保存狀態。
router/index.js
頁面組件引用
導航欄頁面從共享狀態中讀取導航菜單樹並展示。
views/NavBar/NavBar.vue
views/NavBar/NavBar.vue
頁面按鈕權限
添加權限獲取接口
http/modules/user.js
// 查找用戶的菜單權限標識集合 export const findPermissions = (params) => { return axios({ url: '/user/findPermissions', method: 'get', params }) }
添加權限獲取接口
store/modules/user.js
export default { state: { perms: [], // 用戶權限標識集合 }, getters: { }, mutations: { setPerms(state, perms){ // 用戶權限標識集合 state.perms = perms; } }, actions: { } }
加載權限標識
如下圖所示,在導航守衛路由時加載權限標識並保存狀態。
router/index.js
權限按鈕判斷
封裝了權限操作按鈕組件,在組件中根據外部傳入的權限標識進行權限判斷。
views/Core/KtButton.vue
<template> <el-button :size="size" :type="type" :loading="loading" :disabled="!hasPerms(perms)" @click="handleClick"> {{label}} </el-button> </template> <script> import { hasPermission } from '@/permission/index.js' export default { name: 'KtButton', props: { label: { // 按鈕顯示文本 type: String, default: 'Button' }, size: { // 按鈕尺寸 type: String, default: 'mini' }, type: { // 按鈕類型 type: String, default: null }, loading: { // 按鈕加載標識 type: Boolean, default: false }, disabled: { // 按鈕是否禁用 type: Boolean, default: false }, perms: { // 按鈕權限標識,外部使用者傳入 type: String, default: null } }, data() { return { } }, methods: { handleClick: function () { // 按鈕操作處理函數 this.$emit('click', {}) }, hasPerms: function (perms) { // 根據權限標識和外部指示狀態進行權限判斷 return hasPermission(perms) & !this.disabled } }, mounted() { } } </script> <style scoped> </style>
權限判斷邏輯
src/permission/index.js
import store from '@/store' /** * 判斷用戶是否擁有操作權限 * 根據傳入的權限標識,查看是否存在用戶權限標識集合 * @param perms */ export function hasPermission (perms) { let hasPermission = false let permissions = store.state.user.perms for(let i=0, len=permissions.length; i<len; i++) { if(permissions[i] === perms) { hasPermission = true; break } } return hasPermission }
權限按鈕引用
views/Sys/User.vue
測試效果
1.可用狀態,操作按鈕可用。
2.修改頁面的權限標識,導致認證失敗。
如下圖所示,修改新增和刪除按鈕的權限標識(加個2),導致權限認證失敗。
3.無權限,操作按鈕禁用。
新增和刪除按鈕因為修改了權限標識,匹配失敗,變成了禁用狀態。
源碼下載
后端:https://gitee.com/liuge1988/kitty
前端:https://gitee.com/liuge1988/kitty-ui.git