不一樣的權限對應不一樣的路由(菜單),同時側邊欄也根據權限異步生成,實現登陸和鑑權思路以下:前端
- 登陸:點擊登陸,服務器驗證經過後返回一個 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