摘要:權限系統后臺管理系統一般都會有權限模塊,用來控制用戶能訪問哪些頁面和哪些數據接口。大多數管理系統的頁面都長這樣。表為角色權限關聯表,一個角色擁有哪些權限是通過這張表查出來的。這樣就是一個賬號角色權限的關系。
vue權限系統
后臺管理系統一般都會有權限模塊,用來控制用戶能訪問哪些頁面和哪些數據接口。大多數管理系統的頁面都長這樣。
左邊為菜單,分為兩級,右邊為圖表顯示區域,有增刪改查的按鈕。
表的結構SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for t_auth_rule -- ---------------------------- DROP TABLE IF EXISTS `t_auth_rule`; CREATE TABLE `t_auth_rule` ( `id_pk` bigint(20) NOT NULL AUTO_INCREMENT, `auth_id` varchar(128) NOT NULL COMMENT "權限Id", `pauth_id` varchar(128) DEFAULT NULL COMMENT "父級Id", `auth_name` varchar(255) NOT NULL COMMENT "權限名稱", `auth_icon` varchar(255) NOT NULL COMMENT "權限圖標", `auth_type` smallint(6) NOT NULL COMMENT "權限類型,BIT表示其屬性 0x00表示可顯示的菜單權限節點; 0x01表示普通節點", `auth_condition` text COMMENT "條件", `remark` varchar(255) DEFAULT NULL COMMENT "備注", `is_menu` smallint(255) DEFAULT "0" COMMENT "是否為菜單,0表示非,1表示是", `weight` int(11) NOT NULL DEFAULT "0" COMMENT "權重", `rule` varchar(256) DEFAULT NULL COMMENT "規則路徑主要對應菜單或方法的路徑名稱", `cr_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT "創建時間", `up_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT "更新時間", PRIMARY KEY (`id_pk`), UNIQUE KEY `AK_auth_id` (`auth_id`) ) ENGINE=InnoDB AUTO_INCREMENT=264 DEFAULT CHARSET=utf8 COMMENT="權限規則表,記錄權限相關的信息,權限以父子關系存在,菜單是權限的一種。"; SET FOREIGN_KEY_CHECKS = 1; SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for t_role_auth -- ---------------------------- DROP TABLE IF EXISTS `t_role_auth`; CREATE TABLE `t_role_auth` ( `id_pk` bigint(20) NOT NULL AUTO_INCREMENT, `role_id_fk` varchar(32) DEFAULT NULL COMMENT "角色id", `auth_id_fk` varchar(128) DEFAULT NULL COMMENT "權限id", `aa` varchar(255) DEFAULT NULL, PRIMARY KEY (`id_pk`) ) ENGINE=InnoDB AUTO_INCREMENT=77 DEFAULT CHARSET=utf8 COMMENT="角色與權限的關系表"; SET FOREIGN_KEY_CHECKS = 1;
稍微解釋一下表結構,t_auth_rule 表用來存儲對應的權限菜單,一般來說,菜單分為一級和二級菜單,rule字段對應前端的路由規則;而按鈕為第三級,rule對應的是接口url地址。
t_role_auth 表為角色權限關聯表,一個角色擁有哪些權限是通過這張表查出來的。當然還有一個role表,還有一個賬號表,賬號表里有一個role的外鍵。
這樣就是一個賬號 --> 角色 --> 權限的關系。
// 本地寫好路由列表(需要進行動態匹配的) export const routerList: Array= [ // 首頁 { path: "/", name: "_home", redirect: "/home", component: Layout, meta: { hideInMenu: true, notCache: true }, children: [ { path: "home", name: "home", meta: { hideInMenu: true, title: "首頁", notCache: true, icon: "md-home" }, component: () => import("@/views/overview-operations/data-center/DataCenter.vue") } ] } ] // 負責將后臺返回的 菜單列表 轉成vue-router所需要的 router list export function toRouterComponent(menuList: Array ) { if (!menuList.length) return [] let routerArr = []; for (let j = 0; j < menuList.length; j++) { let obj; let firstIndex = routerList.findIndex(i => i.path === menuList[j].url); // 一級菜單 if (firstIndex !== -1) { let children: Array = [] obj = { path: routerList[firstIndex].path, component: routerList[firstIndex].component, redirect: routerList[firstIndex].redirect, name: routerList[firstIndex].name, meta: routerList[firstIndex].meta, children }; // 如果有子菜單 if (menuList[j].children && menuList[j].children.length) { for (let k = 0; k < menuList[j].children.length; k++) { const _children = routerList[firstIndex].children! let secondIndex = _children.findIndex(i => { let fullpath = ""; if (routerList[firstIndex].path === "/") { fullpath = `${routerList[firstIndex].path}${i.path}`; } else { fullpath = `${routerList[firstIndex].path}/${i.path}`; } return fullpath === menuList[j].children[k].url; }); if (secondIndex !== -1) { obj.children.push(_children[secondIndex]); } } } } if (obj) { routerArr.push(obj); } } return routerArr; } // 根據菜單權限,獲取路由數組 // 本地只保存后臺返回的菜單,在頁面刷新的時候從本地拿到菜單重新調用toRouterComponent生成 路由數組 export function getRouterList() { if (!storage.get("username")) { storage.set("menuTree", ""); // 清空菜單權限數據 } let menuList = storage.get("menuTree") ? storage.get("menuTree") : []; const routerArr = toRouterComponent(menuList); return routerArr; }
menuList,菜單數組(或對象), 由后臺返回; routerList為前端定義的路由表;遍歷routerList,如果routerList的path在menuMap里能找到的話,就表示該路由存在。最后生成一個過濾后的路由表,用vue提供的addRoutes方法動態添加到路由中,并把過濾后的路由表存到本地。
在頁面刷新的時候,從本地獲取路由表,添加到路由表中,代碼如下,constRouterArr為基礎路由表,比如登錄,404等
注意這一步有個問題,由于我寫的storage庫用了JSON.stringify,把路由表中的component(實際為一個函數)丟失了,所以在從本地獲取路由的時候,還要重新生成一個新的路由表,重新把component加上去,即把上面的addrouters重新執行一遍
對于按鈕的權限if (res.data.auth_rule_map) { let obj = {} Object.keys(res.data.auth_rule_map).forEach(i => { // 將所有的按鈕放到一個obj里 key 為接口地址 if (res.data.auth_rule_map[i].is_menu === 0) { // 如果是按鈕 obj[res.data.auth_rule_map[i].rule] = 1 } }) storage.set("btnList", obj); storage.set("menuTree", res.data.auth_rule_map); }
auth_rule_map為接口返回權限map,把按鈕的權限過濾出來存到本地。
將map添加到每個路由組件的data里,(這里有一個問題,怎么判斷一個組件是否是路由組件),目前想到的是通過組件name來判斷,把所有的路由組件放到一個數組里做判斷。
在組件內部的按鈕上加上v-if,如果this.uri__里的uri在uriMap里存在就顯示。
也可以通過方法來判斷,如下面的__isBtnShow,不僅可以控制按鈕的顯示隱藏,還可以控制其樣式,比如顏色等,更加靈活,推薦使用方法來控制
uri = { ADD_MEMBER: "/api/add_member" } export default function install (Vue) { const uriMap = storage.get("btnList") //uriMap["/admin/api/auth_rule/update_auth_rule.action"] = 1 Vue.mixin({ created() { const arr = ["MemberManage", "PayManage", "..."] if (arr.indexOf(this.$options.name) !== -1) { this.dataUri__ = uriMap this.uri__ = uri } }, data() { return { dataUri__: {} } }, methods: { __isBtnShow(uri) { return uriMap[uri] ? "display: inline-block" : "display: none" }, } }) } // 通過方法來控制,更加靈活登出的問題
**登出后要清空緩存,routerArr,btnList 等。
由于之前登錄,調用addRouter把權限上個賬號的路由表加進去了,所以登出后要location.reload()一次,重新實例化路由表,去掉動態添加的路由,只保留基礎路由。
location.reload()體驗不是太好,但是vue-router沒有提供動態刪除路由的api,比如 deleteRouter。**
能想到的解決方法是存一個loginIndex 來表示登錄賬號的個數,比如第一次登錄的時候存一個loginIndex=0, 后面存數據的時候都把這個參數帶上;后面登多個賬號的時候個loginIndex++,這樣localStorage的key就是一個動態的(這樣還是不行)
最簡單的方法是存到localStorage里,只有登出才會清空緩存,只能登一個賬號。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/101115.html
摘要:二接口訪問的權限控制接口權限就是對用戶的校驗。代碼如下按扭權限指令至此為止,權限控制流程就已經完全結束了,在最后我們再看一下完整的權限控制流程圖吧五路由控制完整流程圖六參考文獻手擼后臺管理網站之權限控制手摸手,帶你用擼后臺之權限控制 原文首發于我的博客,歡迎點擊查看獲得更好的閱讀體驗~ 一、前言 在廣告機項目中,角色的權限管理是卡了挺久的一個難點。首先我們確定的權限控制分為兩大部分,其...
摘要:二接口訪問的權限控制接口權限就是對用戶的校驗。代碼如下按扭權限指令至此為止,權限控制流程就已經完全結束了,在最后我們再看一下完整的權限控制流程圖吧五路由控制完整流程圖六參考文獻手擼后臺管理網站之權限控制手摸手,帶你用擼后臺之權限控制 原文首發于我的博客,歡迎點擊查看獲得更好的閱讀體驗~ 一、前言 在廣告機項目中,角色的權限管理是卡了挺久的一個難點。首先我們確定的權限控制分為兩大部分,其...
摘要:二接口訪問的權限控制接口權限就是對用戶的校驗。代碼如下按扭權限指令至此為止,權限控制流程就已經完全結束了,在最后我們再看一下完整的權限控制流程圖吧五路由控制完整流程圖六參考文獻手擼后臺管理網站之權限控制手摸手,帶你用擼后臺之權限控制 原文首發于我的博客,歡迎點擊查看獲得更好的閱讀體驗~ 一、前言 在廣告機項目中,角色的權限管理是卡了挺久的一個難點。首先我們確定的權限控制分為兩大部分,其...
摘要:路由不可見實現方法在中的字段中加入該路由的訪問權限列表字段。元素不可見實現方法因為某些頁面中會有一些特殊的接口調用或數據展示受到權限控制顯示。 在Vue項目中實現權限控制管理 對于一般稍大一些的后臺管理系統,往往有很多個人員需要使用,而不同的人員也對應了不同的權限系統,后端的權限校驗保障了系統的安全性,而前端的權限校驗則提供了優秀的交互體驗。 校驗方式 前端對用戶的權限信息進行校驗往往...
摘要:路由不可見實現方法在中的字段中加入該路由的訪問權限列表字段。元素不可見實現方法因為某些頁面中會有一些特殊的接口調用或數據展示受到權限控制顯示。 在Vue項目中實現權限控制管理 對于一般稍大一些的后臺管理系統,往往有很多個人員需要使用,而不同的人員也對應了不同的權限系統,后端的權限校驗保障了系統的安全性,而前端的權限校驗則提供了優秀的交互體驗。 校驗方式 前端對用戶的權限信息進行校驗往往...
摘要:前言本文主要使用來實現前后端分離的認證登陸和權限管理,適合和我一樣剛開始接觸前后端完全分離項目的同學,但是你必須自己搭建過前端項目和后端項目,本文主要是介紹他們之間的互通,如果不知道這么搭建前端項目的同學可以先找別的看一下。 前言 本文主要使用spring boot + shiro + vue來實現前后端分離的認證登陸和權限管理,適合和我一樣剛開始接觸前后端完全分離項目的同學,但是你必...
閱讀 2267·2021-11-25 09:43
閱讀 3138·2021-10-14 09:42
閱讀 3492·2021-10-12 10:12
閱讀 1578·2021-09-07 10:17
閱讀 1910·2019-08-30 15:54
閱讀 3193·2019-08-30 15:54
閱讀 1568·2019-08-30 15:53
閱讀 1926·2019-08-29 11:21