前端权限管理
# 一、权限管理
权限控制是中后台系统中常见的需求之一,你可以利用我们提供的 路由权限
和 指令权限
,实现一些基本的权限控制功能,脚手架中也包含了几个简单示例以提供参考。
# 1.1 路由和默认权限控制
Plus
提供了两套权限实现方案,其中默认方案为前端固定路由表和权限配置,由后端提供用户权限标识,来识别是否拥有该路由权限。另一套方案为后端提供权限和路由信息结构接口,动态生成权限和菜单。
默认实现方式是通过获取当前用户的权限去比对路由表,生成当前用户具有的权限可访问的路由表,通过 router.addRoutes 动态挂载到 router 上。
整体流程可以看这张图:
# 步骤如下:
- 判断是否有
AccessToken
如果没有则跳转到登录页面 - 获取用户信息和拥有权限
store.dispatch('GetInfo')
- 用户信息获取成功后, 调用
store.dispatch('GenerateRoutes', userInfo)
根据获取到的用户信息构建出一个已经过滤好权限的路由结构(src/store/modules/permission.js
) - 将构建的路由结构信息利用
Vue-Router
提供的动态增加路由方法router.addRoutes
加入到路由表中 - 加入路由表后将页面跳转到用户原始要访问的页面,如果没有 redirect 则进入默认页面 (/dashboard/workplace)
这里可以看出把 登录 和 获取用户信息 分成了两个接口,主要目的在于当用户刷新页面时,可以根据登录时获取到的身份令牌(cookie/token)等,去获取用户信息,从而避免刷新需要调用登录接口
Plus
实现的路由权限的控制代码都在 @/permission.js 中,如果想修改逻辑,直接在适当的判断逻辑中 next() 释放钩子即可。 两套权限实现 均使用 @/permission.js (路由守卫)来进行控制。
# 1.2 主要流程
- 在
permission.js
中,添加了全局路由守卫,路由切换时验证登录状态,即本地是否有token - 如果本地没有存储
token
则跳转至登陆界面,登录成功后将token
存储在本地,后续请求携带token
凭证进行鉴权; - 在路由跳转时,新的路由渲染之前,调用方法凭
token
获取用户信息,存储在Vuex中。 - 若用户信息获取失败(通常是因为token过期导致鉴权失败),会导致系统跳转至登陆界面,重新登录以获得有效的token。
- 若用户信息获取成功,则进入系统。
# 1.3 权限管理
通过Getinfo方法,发起请求获取这个账号的权限信息
路径地址: src/store/modules/user.js
// 获取用户信息
GetInfo({ commit }) {
return new Promise((resolve, reject) => {
getLoginUser()
.then(response => {
if (response.code === 200) {
const data = response.data;
commit('SET_ADMINTYPE', data.adminType);
commit('SET_ROLES', 1);
commit('SET_BUTTONS', data.permissions);
commit('SET_INFO', data);
commit('SET_NAME', { name: data.name, welcome: welcome() });
commit('SET_TENANTID', data.tenantId === '' ? '1' : data.tenantId);
Vue.ls.set(TENANT_ID, data.tenantId === '' ? '1' : data.tenantId);
if (data.avatar != null) {
commit('SET_AVATAR', data.avatar);
}
resolve(data);
} else {
// eslint-disable-next-line no-undef
reject(new Error(data.message));
}
})
.catch(error => {
reject(error);
});
});
},
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
之后我们将map返回的权限相关信息存储到vuex中,这样我们就能全局获取到这个用户的权限了 同时将登录用户的账号权限信息return回permission.js中继续下一步操作
我们获取用户权限信息的目的就是拿用户权限与路由表进行匹配,筛选出与之相符合的路由,我们把视线转移到permission.js中,当获取到用户的权限信息后,下一步操作就是要去匹配路由表了,代码如下:
store.dispatch('GenerateRoutes', { antDesignmenus }).then(() => {
// 动态添加可访问路由表
router.addRoutes(store.getters.addRouters);
// 请求带有 redirect 重定向时,登录自动重定向到该地址
const redirect = decodeURIComponent(from.query.redirect || to.path);
if (to.path === redirect) {
next({ path: redirect });
// hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
next({ ...to, replace: true });
} else {
// 跳转到目的路由
next({ path: redirect });
}
});
})
.catch(() => {
store.dispatch('Logout').then(() => {
next({ path: '/user/login', query: { redirect: to.fullPath } });
});
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
在GetInfo的回调函数内,调用了GenerateRoutes方法,我们需要做的就是将在GetInfo中获取到的用户账号信息以参数的方式传递到GenerateRoutes中
路径地址: src/store/modules/permission.js