后台管理系统之权限管理
大致思路:
首先调用登录接口获取到token,把token存储在cookie中,保证刷新页面能记住用户登录状态,登录成功后把token添加在每个请求的请求头中,页面中的请求才能顺利请求到结果。在全局钩子router.beforeEach中拦截路由,判断是否已获得token,判断获取到token后,调用user_info的接口来获取用户的详细信息,如用户权限,用户名,角色等信息。再根据获取到的role动态算出当前用户对应的有权限的路由,再通过router.addRoutes动态挂载这些路由。
首先
在router.js中把路由分为不需要权限的公共页面,如首页和登录页,和需要权限控制的页面,这里可以使用meta来标识该角色能访问的权限页面有哪些,实例化vue的时候只挂载不需要权限的公共页面。
// router.js
import Vue from 'vue';
import Router from 'vue-router';
import Login from '../views/login/';
const dashboard = resolve => require(['../views/dashboard/index'], resolve);
//使用了vue-routerd的[Lazy Loading Routes
](https://router.vuejs.org/en/advanced/lazy-loading.html)
//所有权限通用路由表
//如首页和登录页和一些不用权限的公用页面
export const constantRouterMap = [
{ path: '/login', component: Login },
{
path: '/',
component: Layout,
redirect: '/dashboard',
name: '首页',
children: [{ path: 'dashboard', component: dashboard }]
},
]
//实例化vue的时候只挂载constantRouter
export default new Router({
routes: constantRouterMap
});
//异步挂载的路由
//动态需要根据权限加载的路由表
export const asyncRouterMap = [
{
path: '/permission',
component: Layout,
name: '权限测试',
meta: { role: ['admin','super_editor'] }, //页面需要的权限
children: [
{
path: 'index',
component: Permission,
name: '权限测试页',
meta: { role: ['admin','super_editor'] } //页面需要的权限
}]
},
{ path: '*', redirect: '/404', hidden: true }
];
其次:
在main.js中的router.beforeEach路由拦截中,首先判断是否有token,如果没有token,重定向到登录页,如果有token,再判断是否要跳转到登录页,如果是,就跳转到首页,否则再判断用户是否通过user_info获取到了用户信息,如果是,就跳转到指定页面,否则就调用user_info接口拉取用户信息,获取到用户的role,根据role和路由中的meta过滤出有权限的页面,然后通过router.addRoutes动态挂载这些路由。
// main.js
router.beforeEach((to, from, next) => {
if (store.getters.token) { // 判断是否有token
if (to.path === '/login') {
next({ path: '/' });
} else {
if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(res => { // 拉取info
const roles = res.data.role;
store.dispatch('GenerateRoutes', { roles }).then(() => { // 生成可访问的路由表
router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
})
}).catch(err => {
console.log(err);
});
} else {
next() //当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的全面会自动进入404页面
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
next();
} else {
next('/login'); // 否则全部重定向到登录页
}
}
});
// store/permission.js
import { asyncRouterMap, constantRouterMap } from 'src/router';
function hasPermission(roles, route) {
if (route.meta && route.meta.role) {
return roles.some(role => route.meta.role.indexOf(role) >= 0)
} else {
return true
}
}
const permission = {
state: {
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 { roles } = data;
const accessedRouters = asyncRouterMap.filter(v => {
if (roles.indexOf('admin') >= 0) return true;
if (hasPermission(roles, v)) {
if (v.children && v.children.length > 0) {
v.children = v.children.filter(child => {
if (hasPermission(roles, child)) {
return child
}
return false;
});
return v
} else {
return v
}
}
return false;
});
commit('SET_ROUTERS', accessedRouters);
resolve();
})
}
}
};
export default permission;
浙公网安备 33010602011771号