最近在做一个基于vue+elementUI+es6的后台管理系统,权限管理这块是非常重要的,这块是前台来做的。
- 配置动态路由和静态路由
- 通过后台传过来的isAdmin来判断是管理员权限还是非管理员权限
- 管理员权限就不用递归遍历路由,直接开放所有权限,否则就要递归遍历路由
- *对于三级路由的处理
- 对于白名单的处理
- 创建新用户,权限的保存
配置动态路由和静态路由
对于那些始终要开放的权限,放在静态路由里。比如登录啊,密码的修改等等
通过后台传过来的isAdmin来判断是管理员权限还是非管理员权限
全局守卫
你可以使用 router.beforeEach 注册一个全局前置守卫:
const router = new VueRouter({ … })
router.beforeEach((to, from, next) => {
// …
})
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
每个守卫方法接收三个参数:
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
const whiteList = ['/login','/password']// no redirect whitelist
router.beforeEach((to, from, next) => {
NProgress.start() // start progress bar
if (getToken()) { // determine if there has token
/* has token*/
if (to.path === '/login') {
next({ path: '/' })
NProgress.done()
} else {
if (store.getters.name.length === 0) { // 判断当前用户是否已拉取完user_info信息
store.dispatch('GetUserInfo').then(res => { // 拉取user_info
/**
* note: roles must be a array! such as:
* [
* {
* name:'pageview',
* services:['/user/info','/user/list'],
* children:[
* {
* name:'pageview',
* services:['/user/info','/user/list'],
* }
* ]
* }
* ]
* */
const roles = res.data.roles
const isAdmin = res.data.isAdmin
store.dispatch('GenerateRoutes', { isAdmin, roles }).then(() => { // 根据roles权限生成可访问的路由表
router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
console.dir(store.getters.addRouters)
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
})
}).catch(() => {
store.dispatch('FedLogOut').then(() => {
Message.error('Verification failed, please login again')
next({ path: '/login' })
})
})
} else {
next()
}
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
next()
} else {
next('/login') // 否则全部重定向到登录页
NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
}
}
})
router.afterEach(() => {
NProgress.done() // finish progress bar
})
这里边设置login登录和password密码修改为白名单,可以直接免登陆,进入白名单,根据后台传过来的roles生成可进行访问的路由表
import { asyncRouterMap, constantRouterMap } from '@/router'
/**
* 通过meta.role判断是否与当前用户权限匹配
* @param roles
* @param route
*/
function hasPermission(roles, route) {
const checker = roles.filter(role => {
if (route.name === role.name || route.threechil == true) {
return true
} else {
if (role.children && role.children.length > 0) {
return hasPermission(role.children, route)
}
}
})
return checker.length
}
/**
* 递归过滤异步路由表,返回符合用户角色权限的路由表
* @param asyncRouterMap
* @param roles
*/
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
}
const permission = {
state: {
asyncRouters: JSON.parse(JSON.stringify(asyncRouterMap)),
routers: constantRouterMap,
addRouters: [],
},
mutations: {
SET_ROUTERS: (state, routers) => {
state.addRouters = routers
state.routers = constantRouterMap.concat(routers)
}
},
actions: {
GenerateRoutes({ commit }, data) {
return new Promise(resolve => {
const { isAdmin, roles } = data
let accessedRouters
if (isAdmin == '1') {
accessedRouters = asyncRouterMap
}else if(isAdmin == '0') {
accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
accessedRouters.push(asyncRouterMap[asyncRouterMap.length - 1]);
}
commit('SET_ROUTERS', accessedRouters)
resolve()
})
}
}
}
export default permission
这里边便是进行前台权限控制的路由代码,这里为什么要有route.threechil == true就开放权限呢,是因为遇到了一个bug
之前一直用管理员账号测试的代码,所以在文章管理里边有一个添加,修改功能,之前是直接把这两个功能的页面作为二级路由和文章管理首页同级,大概是这样的页面:
编辑和新增是一个新页面,但是又不能再侧边栏里边出现,在路由中有一个属性是hidden:true设置之后就不会再侧边栏出现了,但是呢,有个问题就是我做权限保存的时候并不会保存这个页面路由给后台,自然后台也就不会给我传过来,所以我不是管理员权限的时候递归的时候就不会递归到这个页面了,自然404就出现了!所以需要设置三级路由嵌套
要注重二级路由和一级路由里引入的组件component,一级路由引入的组件时layout组件,封装的一个整体侧边栏和上边的标签,而二级路由layer只是一个简单的《rouer-view》,给三级路由都加上threechil:true就是在递归的时候遇到这个属性,就开放权限。
还有一个情况就是,侧边栏最多出现两极,三级菜单是不显示的。
这样的话就需要改一改侧边栏里边遍历的代码了
末尾
写的稍微有点乱,希望能看懂,哈哈