摘要:項(xiàng)目背景物業(yè)管理后臺(tái),不同角色擁有不同權(quán)限采用技術(shù)實(shí)現(xiàn)權(quán)限管理需要后端接口支持,這里僅提供前端解決方案。前端代碼可參考如果有更好的想法和建議,歡迎評(píng)論。
項(xiàng)目背景:物業(yè)管理后臺(tái),不同角色擁有不同權(quán)限
采用技術(shù):Vue.js + Vuex + Element UI
實(shí)現(xiàn) RBAC 權(quán)限管理需要后端接口支持,這里僅提供前端解決方案。大致思路:
因代碼篇幅較大,對(duì)代碼進(jìn)行了刪減,文中 “...” 即為省略的一部分代碼。
首先登錄成功后,從后臺(tái)拉取用戶當(dāng)前可顯示的菜單和可用權(quán)限列表,分別將其存入 store 的 nav(菜單導(dǎo)航) 和 auth(用戶可用權(quán)限) 中,
在用戶切換路由時(shí),判斷是否存在 auth ,如果不存在,則重新獲取,判斷當(dāng)前訪問(wèn)地址 to.meta.alias 是否在
用戶可用權(quán)限列表中,如果不存在,則提示無(wú)權(quán)限,否則進(jìn)入路由。
2. 路由切換前進(jìn)行鑒權(quán)
路由定義的部分代碼,對(duì)每個(gè)路由添加了 meta 屬性,用于鑒權(quán)。
這里 component 采用了異步引入的方式。
// ... // 系統(tǒng)管理 { path: "/system", component: Main, name: "系統(tǒng)管理", redirect: "/system/organization", children: [{ path: "/system/organization", component: () => import ("@/views/System/Organization.vue"), name: "組織結(jié)構(gòu)", // requiresAuth 用于確認(rèn)此地址是否需要驗(yàn)證 // alias 用于獲取后端返回rbac權(quán)限對(duì)應(yīng)的前端路由地址和導(dǎo)航菜單圖標(biāo) meta: {requiresAuth: true, alias: "Pmsadmin/Oragnize/list"} }, { path: "/system/user", component: () => import ("@/views/System/User.vue"), name: "人員管理", redirect: "/system/user/index", children: [ { path: "/system/user/index", component: () => import ("@/views/System/UserList.vue"), name: "職員列表", meta: {requiresAuth: true, alias: "Pmsadmin/Admin/list"} } ] }, { path: "/system/auth", component: () => import ("@/views/System/Auth.vue"), name: "角色管理", meta: {requiresAuth: true, alias: "Pmsadmin/Role/list"} } ] } // ...路由鉤子 beforeEach
router.beforeEach((to, from, next) => { document.title = `${configs.title} - ${to.name}`; const {hasAuth, auth} = store.state.user; // 未拿到權(quán)限,則獲取 if (!hasAuth) { store.dispatch("getUserAuth"); console.log("重新獲取用戶權(quán)限"); // next(); } // 如果未登錄,跳轉(zhuǎn) if (window.localStorage.getItem("IS_LOGIN") === null && to.path !== "/login") { console.log("未登錄狀態(tài)"); next({ path: "/login", query: {redirect: to.fullPath} // 將跳轉(zhuǎn)的路由path作為參數(shù),登錄成功后跳轉(zhuǎn)到該路由 }) } else { // 需要鑒權(quán)的路由地址 console.log(to, auth.indexOf(to.meta.alias), auth); if (to.meta.requiresAuth) { if (auth.indexOf(to.meta.alias) > -1) { console.log("有權(quán)限進(jìn)入"); next(); } else { if(auth.length > 0) { Message.error({ message: "當(dāng)前用戶權(quán)限不足,無(wú)法訪問(wèn)", showClose: true, }); } else { next(); } } } else { next(); } } });在 Vuex 的 state 中,定義好 nav 對(duì)象
// 登錄用戶信息 const user = { name: "", // 用戶名 avatar: "", // 用戶頭像 auth: [], // 用戶權(quán)限 hasAuth: false // 是否已經(jīng)加載用戶權(quán)限 }; // 導(dǎo)航菜單 const nav = [];通過(guò) action 異步獲取數(shù)據(jù)
// 獲取用戶權(quán)限 const getUserAuth = async ({commit}) => { const res = await http.post("YOUR_URL", {}); if (res === null) return; console.log("getUserAuth", res.param); commit("SET_USER_AUTH", res.param.auth); commit("SET_SIDE_NAV", res.param.nav); };Vuex 中的 mutation 的相關(guān)代碼
// 設(shè)置用戶權(quán)限 const SET_USER_AUTH = (state, auth) => { state.user.auth = auth.concat("歡迎使用"); state.user.hasAuth = true; }; // 設(shè)置導(dǎo)航菜單 const SET_SIDE_NAV = (state, nav) => { // 導(dǎo)航菜單 let _nav = [{ name: "歡迎使用", url: "/main", iconCls: "fa fa-bookmark" }]; // 權(quán)限菜單對(duì)應(yīng)的路由地址 const route = { "系統(tǒng)管理": {iconCls: "fa fa-archive", url: ""}, "Pmsadmin/Oragnize/list": {iconCls: "", url: "/system/organization"}, "Pmsadmin/Admin/list": {iconCls: "", url: "/system/user/index"}, "Pmsadmin/Role/list": {iconCls: "", url: "/system/auth"}, "Pmsadmin/Log/record": {iconCls: "", url: "/system/logs"}, "項(xiàng)目管理": {iconCls: "fa fa-unlock-alt", url: ""}, "Pmsadmin/Project/list": {iconCls: "", url: "/project/list/index"}, "Pmsadmin/House/list": {iconCls: "", url: "/project/house"}, "Pmsadmin/Pack/list": {iconCls: "", url: "/project/pack"}, "廣告位": {iconCls: "fa fa-edit", url: ""}, "Pmsadmin/Place/list": {iconCls: "", url: "/adsplace/list"}, "投訴建議": {iconCls: "fa fa-tasks", url: ""}, "Pmsadmin/Scategory/list": {iconCls: "", url: "/complain/type"}, "Pmsadmin/Complain/list": {iconCls: "", url: "/complain/list"}, "Pmsadmin/Suggest/list": {iconCls: "", url: "/complain/suggestion"}, "報(bào)事報(bào)修": {iconCls: "fa fa-user", url: ""}, "Pmsadmin/Rcategory/list": {iconCls: "", url: "/rcategory/type"}, "Pmsadmin/Rcategory/info": {iconCls: "", url: "/rcategory/public"}, "Pmsadmin/Repair/list": {iconCls: "", url: "/rcategory/personal"}, "便民服務(wù)": {iconCls: "fa fa-external-link", url: ""}, "Pmsadmin/Bcategory/list": {iconCls: "", url: "/bcategory/type"}, "Pmsadmin/Service/list": {iconCls: "", url: "/bcategory/list"}, "首座推薦": {iconCls: "fa fa-file-text", url: ""}, "Pmsadmin/stcategory/list": {iconCls: "", url: "/stcategory/type"}, "Pmsadmin/Store/list": {iconCls: "", url: "/stcategory/list"}, "招商租賃": {iconCls: "fa fa-leaf", url: ""}, "Pmsadmin/Bussiness/list": {iconCls: "", url: "/bussiness/list"}, "Pmsadmin/Company/list": {iconCls: "", url: "/bussiness/company"}, "Pmsadmin/Question/list": {iconCls: "", url: "/bussiness/question"}, "停車找車": {iconCls: "fa fa-ra", url: ""}, "Pmsadmin/Cplace/list": {iconCls: "", url: "/cplace/cmanage"}, "Pmsadmin/Clist/list": {iconCls: "", url: "/cplace/clist"}, "Pmsadmin/Cquestion/list": {iconCls: "", url: "/cplace/cquestion"}, }; for (let key in nav) { let item = nav[key]; let _temp = {}; let subItems = []; // 二級(jí)菜單臨時(shí)數(shù)組 if (item.children && item.children.length > 0) { // 二級(jí)菜單 item.children.forEach(subItem => { subItems.push(Object.assign({}, { name: subItem.name || "", url: route[subItem.url].url || "", iconCls: route[subItem.url].iconCls || "", })) }); // 一級(jí)菜單 _temp = Object.assign({}, { name: item.name || "", url: item.url || "", iconCls: route[item.name].iconCls || "", children: subItems.slice(0) }); _nav.push(_temp); } } state.nav = _nav; };3. 后端接口返回內(nèi)容
{ "status": 200, "info": "數(shù)據(jù)查詢成功!", "param": { "nav": { "1": { "name": "系統(tǒng)管理", "url": "", "children": [ { "name": "組織結(jié)構(gòu)", "url": "Pmsadmin/Oragnize/list" }, { "name": "人員管理", "url": "Pmsadmin/Admin/list" }, { "name": "角色管理", "url": "Pmsadmin/Role/list" }, { "name": "日志管理", "url": "Pmsadmin/Log/record" } ] }, "61": { "name": "廣告位", "url": "", "children": [ { "name": "廣告位列表", "url": "Pmsadmin/Place/list" } ] } }, "auth": [ "系統(tǒng)管理", "Pmsadmin/Oragnize/list", "Pmsadmin/Admin/list", "Pmsadmin/Role/list", "Pmsadmin/Log/record", "廣告位", "Pmsadmin/Place/list" ] } }存在的問(wèn)題
新增 修改 刪除 按鈕還無(wú)法實(shí)現(xiàn)根據(jù)用戶權(quán)限控制其顯示
代碼上還存在著不足,期待大神能夠有更優(yōu)的解決方案。
前端代碼可參考:https://github.com/kfw001/adm...
如果有更好的想法和建議,歡迎評(píng)論。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/91765.html
摘要:權(quán)限設(shè)計(jì)的雜談這篇文章的定位,不是宣傳某個(gè)框架,僅僅之是梳理一下有關(guān)權(quán)限方面的一些想法和最近項(xiàng)目中的一些探索過(guò)程。而這兩者的取舍則是有設(shè)計(jì)人員決定的。數(shù)據(jù)抽象原則最小特權(quán)劃分從某個(gè)程度上來(lái)說(shuō)決定了控制的對(duì)象,而數(shù)據(jù)抽象原則是是決定了操作。 權(quán)限設(shè)計(jì)的雜談 這篇文章的定位,不是宣傳某個(gè)框架,僅僅之是梳理一下有關(guān)權(quán)限方面的一些想法和最近項(xiàng)目中的一些探索過(guò)程。我們主要想解決一下問(wèn)題。 什么...
摘要:例如,系統(tǒng)中某個(gè)用戶辭職了,只需要將系統(tǒng)中該用戶的角色授權(quán)撤銷即可。 Q0.有哪些概念需要知道? 一些概念的具體定義如下 用戶(user): 和計(jì)算機(jī)系統(tǒng)交互的人(在許多設(shè)計(jì)方案中,單個(gè)用戶可能擁有多個(gè)登錄標(biāo)識(shí)(ID),這些標(biāo)識(shí)可能同時(shí)處于活躍狀態(tài),但身份驗(yàn)證機(jī)制可以使多個(gè)標(biāo)識(shí)匹配到某個(gè)具體的人,即用戶對(duì)于計(jì)算機(jī)系統(tǒng)來(lái)說(shuō)具有唯一性) 主體(subject): 一個(gè)代表用戶行為的計(jì)算機(jī)...
摘要:解決方案如圖所示,將軍令分塊,數(shù)據(jù)內(nèi)容權(quán)限平臺(tái)審批流平臺(tái)審計(jì)日志平臺(tái)提供各種靈活可插拔的服務(wù),支持在通用服務(wù)的基礎(chǔ)基礎(chǔ)上進(jìn)行定制開(kāi)發(fā)。 背景 在大數(shù)據(jù)時(shí)代,數(shù)據(jù)已經(jīng)成為公司的核心競(jìng)爭(zhēng)力。此前,我們介紹了美團(tuán)酒旅起源數(shù)據(jù)治理平臺(tái)的建設(shè)與實(shí)踐,主要是通過(guò)各種數(shù)據(jù)分析挖掘手段,為公司發(fā)展決策和業(yè)務(wù)開(kāi)展提供數(shù)據(jù)支持。 近期,業(yè)內(nèi)數(shù)據(jù)安全事件頻發(fā),給相關(guān)企業(yè)造成了無(wú)可挽回的損失,更為數(shù)據(jù)安全防護(hù)...
閱讀 812·2021-11-23 09:51
閱讀 2525·2021-10-11 11:10
閱讀 1397·2021-09-23 11:21
閱讀 1182·2021-09-10 10:50
閱讀 952·2019-08-30 15:54
閱讀 3390·2019-08-30 15:53
閱讀 3350·2019-08-30 15:53
閱讀 3262·2019-08-29 17:23