不一样的权限对应不一样的路由(菜单),同时侧边栏也根据权限异步生成,实现登陆和鉴权思路以下:前端
- 登陆:点击登陆,服务器验证经过后返回一个 token ,而后存到 cookie,再根据 token 拉取用户权限
- 鉴权:经过 token 获取对应的roles, 计算有权限的路由,使用 router.addRoutes 动态加载路由
数据和操做经过 vuex 进行控制vue
1 登陆
登陆按钮 click 事件触发登陆动做:vue-router
/** ...省略的代码 */ this.$store.dispatch('LoginByUsername', { 'username': username, 'password': password }) .then(() => { this.logining = false this.$notify.success({ message: '欢迎登陆', duration: 3 * 1000, }) // 重定向到首页 this.$router.push({ path: this.redirect || '/' }) }) .catch(err => { this.logining = false this.$alert(err, { type: 'warning', confirmButtonText: 'ok' }) }) /** ...省略的代码 */
action:vuex
// 登入 LoginByUsername({commit }, userInfo){ const username = userInfo.username.trim() return new Promise((resolve, reject) => { loginByUsernameApi(username, userInfo.password) .then(response=> { const data = response.data setToken(data.token) // 储存token commit('SET_TOKEN', data.token) commit('SET_ACCOUNT', username) resolve() }) .catch(err => { reject(err) }) }) } /** ...省略的代码 */
登陆成功,服务端返回一个token,而后储存到本地 cookie。后端
2 获取用户权限
对每一个路由,在全局钩子 router.beforeEach 中拦截,判断是否已获取token,以后再获取用户的基本信息服务器
/** ...省略的代码 */ if(store.getters.token) { // 判断当前用户是否已拉取完user_info信息 if(store.getters.roles.length === 0){ // 拉取用户信息 store.dispatch('GetUserInfo').then(resp => { const roles = resp.data.roles next() /** ...省略的代码 */ }) }) } } /** ...省略的代码 */
action:cookie
// 获取用户信息, 名称、头像、权限 GetUserInfo({commit, state}) { return new Promise((resolve, reject) => { getLoginUserInfoApi(state.token) .then(response => { if(!response.data){ reject('error') } const data = response.data const roles = data.data if(roles && roles.length > 0){ commit('SET_ROLES', roles) }else { reject() } if(data.name){ commit('SET_NAME', data.name) } if(data.avatar){ commit('SET_AVATAR', data.avatar) } response.data.roles = roles resolve(response) }) .catch(err => { reject(err) }) }) },
3 菜单权限
前端保存一份路由表,记录每个路由和须要的权限。
再根据用户信息里的 roles 计算对应的权限,而后生成有权限的菜单,再挂载路由。
但这只是页面控制,后端也要相应的作权限验证。异步
- 建立vue实例时使用vue-router挂载登陆和一些公用页面,如首页、图表等
- 用户登陆后,将获取的roles和路由表的权限比较,生成用户可访问的路由表
- 调用router.addRoutes添加可访问的路由
- 使用vuex管理路由表,生成侧边栏菜单
首先是 router.js 路由表async
import Vue from 'vue' import Router from 'vue-router' import Container from '@/containers/Container' import Login from '@/views/login' import Page404 from '@/views/404' import Dashboard from '@/views/dashboard' /** router modules */ import systemRouter from './modules/system' Vue.use(Router) export const constantRouterMap = [ { path: '/login', hidden: true, component: Login }, { path: '/404', hidden: true, component: Page404 }, { path: '/', redirect: '/dashboard', component: Container, name: '首页', hidden: false, meta: { title: '首页', icon: '', noCache: true }, children: [ { path: 'dashboard', name: 'Dashboard', component: Dashboard, meta: { title: '首页', icon: 'fa fa-dashboard fa-lg', noCache: true } }, { path: 'table', name: '表格综合实例', component: Form, meta: { title: '表格综合实例', icon: '', noCache: true } }, // { path: '*', redirect: '/404', hidden: true } ] }, ] export default new Router({ mode: 'hash', scrollBehavior: () => ({ y: 0 }), routes: constantRouterMap }) export const asyncRouterMap = [ /** 其余的异步路由表 */ systemRouter, { path: '*', redirect: '/404', hidden: true } ]
同级目录下的 ./modules/system.js 路由表this
import Container from '@/containers/Container' /** * 系统管理相关路由 */ const systemRouter = { path: '/system', component: Container, redirect: '/system/permit/account', name: '系统管理', meta: { title: '系统管理', roles: ['/system'] }, children: [ { path: 'permit', name: '权限管理', hidden: false, redirect: '/system/permit/account', component: () => import('@/views/system/permit'), meta: { title: '权限管理', icon: 'fa fa-cog fa-lg', roles: ['/system/permit'] }, children: [ { path: 'account', name: '用户', component: () => import('@/views/system/permit/account'), meta: { title: '用户', icon: 'form', roles: ['/system/permit/account'] } }, { path: 'accountgroup', name: '用户组', component: () => import('@/views/system/permit/accountgroup'), meta: { title: '用户组', icon: 'form', roles: ['/system/permit/accountgroup'] } }, { path: 'role', name: '角色', component: () => import('@/views/system/permit/role'), meta: { title: '角色', icon: 'form', roles: ['/system/permit/role'] } }, { path: 'authorize', name: '受权', component: () => import('@/views/system/permit/authorize'), meta: { title: '受权', icon: 'form', roles: ['/system/permit/authorize'] } }, ] }, ], } export default systemRouter
roles: ['/system/permit/account'] 表示该页面须要的权限是 '/system/permit/account' 后端返回的 roles 里有这个记录则能访问对应的页面
而 '/system/permit/account' 是 '/system/permit' 的子路由,因此要访问 '/system/permit/account',后端返回:
roles: ['/system', '/system/permit', '/system/permit/account']
注意: 404页面要最后加载,若是放在 constantRouterMap 中,全部后面的页面都会被拦截到404