说到后台管理系统,就免不了涉及到权限的管理。在项目中,主要遇到的有两种,一种是页面的限制,一种操作按钮的限制。
首先我们聊一下页面的权限限制:
一、路由的配置 (router—> index.js)
1、不对权限做限制的页面(路由的初始配置)
export const constantRouterMap = [
{
path: '/',
name: 'Login',
component: Login
},
{ path: '/404', component: () => import('@/views/errorPage/404'), hidden: true },
{ path: '/401', component: () => import('@/views/errorPage/401'), hidden: true },
]
export default new Router({
// mode: 'history', // 路由开启history模式时,需要进行服务器配置,vue官网有介绍
scrollBehavior: () => ({ y: 0 }),
routes: constantRouterMap
})
2、需要根据不同权限生成不同的路由列表
export const asyncRouterMap = [
{
path: '/home',
name: 'home',
component: Home,
redirect: {
name: "index"
},
meta: {
roles: [0, 1, 2],
isLogin: true
},
children: [
{
path: 'index',
name: 'index',
component: Index,
meta: {
roles: [0, 1, 2]
}
},
{
path: 'client',
name: 'client',
component: Client,
meta: {
roles: [0, 1, 2]
}
},
{
path: 'resource',
name: 'resource',
component: Resoure,
meta: {
roles: [0, 1, 2]
}
},
{
path: 'recommend',
name: 'recommend',
component: Recommend,
meta: {
roles: [0, 1, 2]
}
},
{
path: 'setting/hunter',
name: 'hunter',
component: Hunter,
meta: {
roles: [0, 1, 2]
}
},
{
path: 'setting/handover',
name: 'handover',
component: handOver,
meta: {
roles: [0, 1, 2]
}
},
{
path: 'setting/analysis',
name: 'analysis',
component: analysis,
meta: {
roles: [0, 1, 2]
}
},
{
path: 'setting/department',
name: 'department',
component: departmentSetting,
meta: {
roles: [0]
}
},
{
path: 'setting/employer',
name: 'employer_setting',
component: employerSetting,
meta: {
roles: [0]
}
},
{ path: '*', redirect: '/404', hidden: true } // 404配置需放到路由配置最后,当
// 用户访问没有权限的时候,则会跳
// 转到404页
]
}
]
二、公用方法的提取
// 判断是否有权限方法
export function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.indexOf(role) >= 0)
} else {
return true
}
}
//根据角色、过滤出路由列表
export function filterAsyncRouter(asyncRouterMap, roles) {
const accessedRouters = asyncRouterMap.filter(route => {
if (hasPermission(roles, route)) {
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, roles)
}
return true
}
return false
})
return accessedRouters
}
三、通过vuex管理一些变量
import Vue from 'vue'
import Vuex from 'vuex'
import { asyncRouterMap, constantRouterMap } from '@/router'
import { filterAsyncRouter } from '@/assets/js/common.js'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
routers: constantRouterMap, // 最终的路由列表
addRouters: [], // 根据权限得到的路由列表
roles: [] // 角色列表,可能一个用户名,存在多个角色,所以用数组的形式
},
mutations: {
SET_ROLES: (state, roles) => {
state.roles = roles
},
SET_ROUTERS: (state, routers) => {
state.addRouters = routers
state.routers = constantRouterMap.concat(routers)
}
},
actions: {
GenerateRoutes({ commit }, data) {
// 当前登录账号的角色数组
return new Promise(resolve => {
const { roles } = data
let accessedRouters
// 如果当前账号级别为0,则拥有所有的权限
if (roles.indexOf(0) >= 0) {
accessedRouters = asyncRouterMap
} else {
// 过滤账户权限
accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
}
commit('SET_ROUTERS', accessedRouters)
resolve()
})
}
}
})
四、登录操作
this.$http.post("/user/login", qs.stringify(this.loginForm)).then(res => {
if (res.data.code === 200) {
cookie.set("userInfo", res.data.data);
this.$router.push({
name: "home"
});
}
});
补充说明:
1、axios默认的数据格式为json,如果后台接口接收的数据格式不是json,则需要通过qs进行序列化处理
2、cookie 、 js为依赖,使用时,请下载以及引入
五、permission.js
import router from './router'
import store from './store'
import { hasPermission } from '@/assets/js/common.js'
import cookie from 'js-cookie'
// 不需要登录就可以访问的页面
const whiteList = ['/', '/404', '/401']
router.beforeEach((to, from, next) => {
const shiroCookie = cookie.get('userInfo')
if (shiroCookie) {
if (store.state.roles.length === 0) {
// 登录操作后,以及当刷新页面是store中的数据恢复到初始值,需要重新设置
const roles = [JSON.parse(cookie.get("userInfo")).position]
store.commit('SET_ROLES', roles)
store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表
router.addRoutes(store.state.addRouters) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
})
} else {
// 没有刷新页面对路由权限验证
if (to.meta.roles && to.meta.roles.length) {
// 当前路由有权限限制时,经过验证后,允许跳转
if (hasPermission(store.state.roles, to.meta.roles)) {
next()
}
} else {
// 不存在权限限制时,则允许跳转
next()
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
// 如果在白名单之列,则允许跳转
next()
} else {
// 如果不在白名单之列,则返回登录页
next('/')
}
}
})
最后在main.js中引入该文件就可以
最后我们可以通过指令来实现操作按钮的权限控制,以及导航栏的渲染。导航栏部分,我们也可以通过配置路由信息,根据store.state.addRouters的值来动态生成。
六、当进行退出操作时的操作
this.$http.post("/user/logout").then(res => {
if (res.data.code === 200) {
cookie.remove("userInfo");
this.$store.commit('SET_ROLES', [])
this.$router.push({
name: "Login"
});
}
});