vue 权限管理
今天来说说权限管理,因为网上已经有很多关于这方面的很多内容,博主也是借鉴了网上的一些逻辑来写的,主要也是说说前端实现权限管理的一个思路,也是作为自己日后面对这样的问题的一个解决方案。首先需要了解的就是纯前端是无法实现权限管理的,vue的权限管理主要是基于路由实现的,当然这样的权限管理完全可以被绕过去的,而之所以在前端这么做,更多是为了用户体验,节省不必要的加载开销等等。用vue来实现权限管理,..
今天来说说权限管理,因为网上已经有很多关于这方面的很多内容,博主也是借鉴了网上的一些逻辑来写的,主要也是说说前端实现权限管理的一个思路,也是作为自己日后面对这样的问题的一个解决方案。
首先需要了解的就是纯前端是无法实现权限管理的,vue的权限管理主要是基于路由实现的,当然这样的权限管理完全可以被绕过去的,而之所以在前端这么做,更多是为了用户体验,节省不必要的加载开销等等。
用vue来实现权限管理,主要就是基于这个新的vue的api,addRoutes的方法来实现的,当然权限管理也分为几个方面,博主今天主要就是说的页面级的权限,思路就是利用刚刚说的api来动态加载路由,我们将路由分为两个部分,一个是公共部分,即所有人都能看到的路由,另外一部分则是动态加载部分,这里也简单的将代码贴出来,大家参考一下就可以,网上的代码也是有很多
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export const constRouterMap = [
{
path: '/login',
name: 'Login',
meta: {
title: '登录',
keepAlive: false
},
component: () => import('@/views/Login.vue')
},
{
path: '/layout',
component: () => import('@/views/Layout.vue'),
// redirect: '/login',
// redirect: '/index',
children: [
{
path: '/index',
name: 'index',
meta: {
title: '首页',
keepAlive: false
},
component: () => import('@/views/HomePage.vue')
},
{
path: '/about',
name: 'about',
meta: {
title: '开发备忘',
keepAlive: false
},
component: () => import('@/views/About.vue')
},
{
path: '/author',
name: 'author',
meta: {
title: '关于作者',
keepAlive: false
},
component: () => import('@/views/AboutAuthor.vue')
},
{
path: '/weather',
name: 'wether-fore',
meta: {
title: '天气预报',
keepAlive: true
},
component: () => import('@/views/WeatherFore.vue')
},
{
path: '/dynamic',
name: 'dynamic-table',
meta: {
title: '动态表格',
keepAlive: false
},
component: () => import('@/views/DynamicTable.vue')
},
{
path: '/editable',
name: 'editable',
meta: {
title: '可编辑表格',
keepAlive: true
},
component: () => import('@/views/TableGrid.vue')
}
]
}
]
export const asyncRouterMap = [
{
path: '/layout',
component: () => import('@/views/Layout.vue'),
children: [
{
path: '/access',
name: 'access',
component: () => import('@/views/AccessTest.vue'),
meta: {
title: '权限控制',
roles: ['admin'],
keepAlive: false
}
},
{
path: '/cube',
name: 'cube',
component: () => import('@/views/MagicCube.vue'),
meta: {
title: '魔幻立方',
roles: ['admin'],
keepAlive: false
}
}
]
},
{
path: '/error',
component: () => import('@/views/NotFound.vue')
},
{
path: '*', redirect: '/error', hidden: true
}
]
export default new Router({
mode: 'history',
routes: constRouterMap
})
看到这个代码应该知道,我们首先是先加载公共路由部分,然后再根据vue-router提供的路由导航钩子,当路由进行跳转的时候,向服务器请求用户的角色权限
import router from './router'
import store from '@/store/index'
import { Message } from 'element-ui'
const whiteList = ['/login']
router.beforeEach((to, from, next) => {
if (sessionStorage.getItem('token')) {
if (to.path === '/') {
next('/index')
} else {
if (store.getters.roles.length === 0) {
const roles = sessionStorage.getItem('roles')
store.dispatch('permission/generateRoute', { roles })
.then(() => {
console.log(store.getters.addRoutes[0].children.length)
router.addRoutes(store.getters.addRoutes)
next({ ...to, replace: true })
})
.catch(err => {
Message.error({ message: err })
})
} else {
next()
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next('/login')
}
}
})
这里后台博主用了thinkjs的框架,博主现在还在整理,后续整理好,也会上传到github上面。在这个导航钩子上,我们利用了vuex来存储角色信息,每次登陆会进行判断,如果没有角色信息,就会去触发action来请求服务器,服务器返回角色字段后,我们将他存在store里面。另外根据上面的路由,我们将页面权限需要的角色放在路由的meta字段中,所以当我们拿到角色信息后,会和动态路由中的meta进行一一对比,需要注意的是,当路由有嵌套的children属性时,我们还需要将children里面的路由拿出来一一进行递归对比,这样如果服务器的角色信息,符合路由需要的权限,我们就将这个路由记录下来,最后组成需要添加的路由,利用addRoutes来形成最终的路由。
generateRoute ({ commit }, data) {
return new Promise((resolve, reject) => {
const roles = []
roles.push(data.roles)
let accessRouters
console.log(roles.indexOf('admin') >= 0)
if (roles.indexOf('admin') >= 0) {
accessRouters = asyncRouterMap
} else {
accessRouters = filterAsyncRouter(asyncRouterMap, roles)
}
// console.log(accessRouters)
commit('SET_ROUTERS', accessRouters)
commit('SET_ROLES', roles)
resolve()
})
},
function hasPermission (roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.indexOf(role) >= 0)
} else {
return true
}
}
function filterAsyncRouter (asyncRouter, roles) {
const accessRouters = asyncRouter.filter(route => {
if (hasPermission(roles, route)) {
if (route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, roles)
}
return true
}
return false
})
// console.log(accessRouters)
return accessRouters
}
结合前面的导航钩子就形成了最终的路由,当用户试图访问不存在的路由的时候,则会返回404页面,另外也简单的说下按钮及页面中视图显示的权限,其实也是利用了vue的自定义指令,我们给自定义指令传入需要的角色权限数组,然后和存储在store中的权限作对比,如果没有权限,则移除当前的DOM元素
import store from '@/store/index'
const permission = {
inserted (el, binding, vnode) {
const { value } = binding
const roles = store.getters && store.getters.roles
if (value && value instanceof Array && value.length > 0) {
const permissionRoles = value
const hasPermission = roles.some(role => {
return permissionRoles.includes(role)
})
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error('roles is must be Array!')
}
}
}
export default permission
这些代码都是博主自己写的项目中的片段,完整的代码,大家有兴趣可以去GitHub上面查看。之前写的权限没有问题,但是重新整理的时候,突然发现权限需要刷新的时候才会生效,技术有限,所以要是有同学发现代码有什么问题,可以随时告诉博主,当然博主也是会继续踩坑下去,解决这个问题。
更多推荐
所有评论(0)