在一些后台管理系統中,每個身份登錄的權限不一樣,以至於配置的菜單不一樣。就我做過的小區物業管理系統而言,舉個例子:業主登錄網站只能看到社區服務中的投訴、維修以及查看公告。而管理員可以看到一些對本小區的基本操作,例如查看樓棟,查看業主,賬單催繳等等…而超級管理員,可以看到所有界面,以及處理一些審核等等一系列。那么這個時候,我們沒必要每個身份做一個系統,而是通過權限管理,對每種身份做配置;
————————————————
上述引用自:CSDN博主「一坨仙女」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_51462774/article/details/117194323
權限管理的實現,其實是需要后台配合的,也可能會根據不同的需求有不同的實現方法。這章的內容主要說要一下我們公司之前后台管理系統的實現思路。
先給同學們描述一下具體的實現步驟:
1、用戶登錄
2、返回權限數據
3、根據權限數據寫攔截器
一、約定權限數據
也就是首先要向后台所有的權限數據放到配置文件中,我這里做的是一個json數組,將每個路由名稱映射到每個對應的權限上面,入下圖所示:
由於具體代碼就不貼了,可以根據截圖在config文件夾下創建config.permission.js文件,然后把每個權限做成鍵值對,鍵名可以通過權限對應的內容來命名,這個鍵名后面在路由配置文件中是用到的。
二、用戶登錄緩存權限數據
當用戶登錄成功之后,拿到了對應的權限數據,這些權限數據有很多地方要用到,所以我們需要做成緩存,一般的話是通過Vuex來緩存,不過這個有個弊端,就是頁面F5刷新之后會丟失。也可以緩存到瀏覽器的storeage,建議存本地緩存的應使用加密方式進行存儲。
先實現個登錄頁面,在view/login/ 文件夾下新建 index.vue 文件,代碼如下:
<template> <div> <h5>我是登錄</h5> <input type="text" v-model="username" placeholder="請輸入用戶名" /> <input type="password" v-model="password" placeholder="請輸入密碼" /> <button @click="login">登錄</button> </div> </template> <script> export default { data() { return { username: '', password: '', } }, methods: { login() { this.$ajax('login/authApi/loginApi', { usernmae: this.username, passwrod: this.password }) .then((res) => { console.log('success', JSON.stringify(res)) }) .catch((rej) => { console.log('fail', rej) }) }, }, } </script>
在App.vue中添加router-view組件:
<template> <div id="app"> <router-view></router-view> </div> </template> <script> export default { name: 'App', components: { }, methods: { }, } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
記得之前的代碼是把路由跳轉給關閉掉了,現在把它開放出來。更改router/index.js 文件
/** * 全局前置守衛 * @func beforeEach * @param {object} to 即將要進入的目標 路由對象 * @param {object} form 當前導航正要離開的路由 * @func next 進行管道中的下一個鈎子 */ router.beforeEach(async (to, from, next) => { next() })
在router/routers.js 導入頁面模塊:
/** * 逐個導出模塊 */ export const constantRoutes = [ { path: '/', redirect: '/home' }, { path: '/login', name: 'login', meta: { title: '登錄', }, component: () => import('../views/login/index.vue') } ] export default [ ...constantRoutes, ]
在使用import導入頁面模塊,由於之前加的代碼規范,是會報錯的,我們在.eslintrc.js文件加入以下代碼就可以了。
//import模塊導入 parserOptions: { parser: 'babel-eslint', ecmaVersion: 10, sourceType: 'module', }, //import模塊導入
最后在瀏覽器地址欄中后面加上/login,就能看到正常跳轉了。
三、路由攔截器
權限控制就是判斷你有哪些權限就可以訪問哪些內容,這里我們來處理一下路由跳轉的攔截。
先寫一個簡單的攔截器,就在utils文件夾下創建intercept文件夾和has-permission.js文件,實際就是一個工具類,根據傳入的權限標識用來判斷是否有權限。
import store from '@/store' import permissionsJson from '@/config/config.permission.js' /** * 判斷用戶是否擁有操作權限 * 根據傳入的權限標識,查看是否存在用戶權限標識集合 * @param perms */ export function hasPermission(perms) { let hasPermission = false let permissions = store.state.user.perms if (permissions.length == 0) { return false } for (let i = 0, len = permissions.length; i < len; i++) { if (permissions[i] === permissionsJson[perms]) { hasPermission = true break } } return hasPermission }
導入的store模塊:
主要是取登錄之后的權限數據,在store/modules/user.js加一下perms屬性,
export default { namespaced: true, state: { userInfo: { id: null, account: '', realName: '', companies: '', sites: null, }, perms: [], //權限集合 }, mutations: { setUserInfo(state, param) { state.userInfo = param }, logout(state, param) { state.userInfo = param }, setPerms(state, perms){ // 用戶權限標識集合 state.perms = perms } }, }
然后在登錄頁面中,在點擊登錄請求后,通this.$store.commit 緩存權限狀態。這里插一句,this.$store.commit 是傳值給vuex中的mutation改變state,這個是同步的方法,異步的是this.$store.dispatch。
登錄頁的代碼如下:
<template> <div> <h5>我是登錄</h5> <input type="text" v-model="username" placeholder="請輸入用戶名" /> <input type="password" v-model="password" placeholder="請輸入密碼" /> <button @click="login">登錄</button> </div> </template> <script> export default { data() { return { username: '', password: '', } }, methods: { login() { this.$ajax('login/authApi/loginApi', { usernmae: this.username, passwrod: this.password }) .then(() => { // console.log('success', JSON.stringify(res)) //模擬登錄成功-狀態緩存權限數據 this.$store.commit('user/setPerms', ['ruleList', 'scenicList']) this.$router.push('home') }) .catch((rej) => { console.log('fail', rej) }) }, }, } </script>
上面api的接口的實現,是通過mockJS實現的,在前端開發過程中,對於mock數據的應用也是很重要的,太久沒寫博客了,忘記前面有沒有細講mockJS導入和使用的問題。如果沒有的話,后面我會用一章節單獨說這個內容。
在view文件夾中創建home頁面
然后在路由中引入:router/routers.js
在權限管理的實現中,一般會分為兩種實現,功能模塊的控制顯示和路由頁面的控制跳轉。
功能模塊的控制顯示。
在home頁面中,查看獲取到的權限列表;
上面是沒有加權限控制顯示的按鈕,通過循環顯示加上控制顯示。
view/home/home.vue代碼如下:
<template> <div> <h5>我是主頁</h5> <template v-for="item in menuList"> <el-button v-if="showBtn(item.persName)" :key="item.persName" :type="item.type">{{ item.name }}</el-button> </template> </div> </template> <script> // import { mapState } from 'vuex' import { hasPermission } from '../../utils/intercept/has-permission' export default { data() { return { menuList: [ { type: 'primary', name: '預約管理', persName: 'preorder', }, { type: 'success', name: '預約管理-預約記錄', persName: 'orderRecord', }, { type: 'info', name: '預約管理-預約數據統計', persName: 'orderStatistics', }, { type: 'warning', name: '預約管理-規則設置', persName: 'ruleSet', }, { type: 'danger', name: '預約管理-規則查詢', persName: 'ruleList', }, ], } }, computed: { // ...mapState({ // permissionList: (state) => state.user.perms, // }), permissionList() { return this.$store.state.user.perms }, }, created() { // console.log('權限數據', this.$store.state.user.perms) }, methods: { showBtn(persName) { console.log('打印權限', persName, hasPermission(persName)) return hasPermission(persName) }, }, } </script>
路由頁面的控制跳轉。
在路由跳轉前置中做好控制,根據權限攔截,有權限通過,沒權限就提示無權限。
在router/index.js中引入權限判斷函數
import { hasPermission } from '../utils/intercept/has-permission'
修改路由跳轉的前置函數:
在需要權限訪問的頁面中,注冊路由的時候,在meta屬性中加入persName屬性,並添加具體的權限名;如訂單頁面:
當點擊home頁面的進行測試,可以看到,對沒有權限的頁面跳轉進行了攔截;
即使知道路由名稱,在地址欄中輸入訪問,也是不起效果的。
-----------------------======================================================================-----------------------
那么后台管理系統實現權限管理這個章節也算講完了,內容有點多,希望大家好好消化一下,多動動手。
一直忘記把代碼倉庫發出來了,抱歉~
附上代碼倉庫:baskstate-sys: 前端修仙之路-后台管理系統框架-源碼 配套學習:博客園-https://www.cnblogs.com/liao123/p/16168755.html 公眾號:padding2020 (gitee.com)