一、权限管理
权限管理就是让不同的用户只能访问自己权限内的资源,根据自己不同的权限去生成不同的页面内容,主要有以下几种:
- 接口权限
- 菜单权限
- 路由权限
- 按钮权限
- 数据权限
1.接口权限
接口权限主要应用于登录操作时,获取token。
思路:
在login.vue中登录成功时,后端会返回token和该用户对应的权限,前端根据权限数据,
但是在login.vue获得的权限数据要在home.vue中使用,所以要把请求来的权限数据保存到vuex中
login方法和权限方法,存储到sessionStorage或localStorage本地,下次请求携带在http请求头中。
axios.interceptors.request.use(config => {
config.headers['token'] = cookie.get('token')
return config
},
function (error) {
return Promise.reject(error);
})
axios.interceptors.response.use(function (response) {
if (response.data.code === 400 || response.data.code === 401) { //token过期或者错误
router.push('/login')
}
return response;
},
function (error) {
return Promise.reject(error);
});
2.菜单权限
- 菜单权限:控制用户在系统中能够看到哪些菜单项,可以理解成将页面与由、路由进行解耦
- 菜单权限指的就是后台系统中的左侧的菜单栏,前端可以根据后端接口返回的权限数据动态生成菜单栏,有什么权限就展示什么菜单
- 通过vuex+持久化插件(本地存储)解决刷新页面菜单栏不显示问题
- 实现退出登录功能时,通过
clear()方法清除本地数据,跳转后通过window.location.reload()刷新当前页面,可实现清除vuex数据的操作
具体过程: 在登录操作时,后台通过用户的账号密码返回相应的菜单权限和token
// 先判断用户是否存在
// 判断账号和密码是否对应
if (username === 'xhope' && password === 's364468777') {
return {
code: 200,
data: {
menu: [
{
path: "/home",
name: "home",
label: "首页",
icon: "HomeFilled",
url: "home/Home.vue",
},
{
path: "/mall",
name: "mall",
label: "商品管理",
icon: "video-play",
url: "Mall/Mall.vue",
},
{
path: "/user",
name: "user",
label: "用户管理",
icon: "user",
url: "User/User.vue",
}
],
token:*************,
message: '获取成功'
}
}
3.路由权限
-
路由权限为了防止用户恶意通过在地址栏输入地址发生强行跳转,可以通过动态路由对用户权限做出相关限制,有权限则跳转,无权限则跳转404页面
-
路由权限的方法需要在两个时机调用,分别是登录成功时和页面创建时,否则动态路由为默认值,刷新无法访问
两种方法:
方法一:在路由初始化的时候挂载全部路由,在路由上标记相应的权限信息,当路由跳转的时候做校验
const router = [{path: 'home',component: () => import('@/views/home'),name: 'homePage',meta: {title: '主页',roles: ['admin','editor'] }
}]
方法二:根据登录后的用户权限信息进行动态创建路由菜单addRoutes表
if (username === 'lzm' && password === '364468777') {
return {
code: 20000,
data: {
menu: [
{
path: '/home',
name: 'home',
label: '首页',
icon: 's-home',
url: 'Home.vue'
},
{
path: '/video',
name: 'video',
label: '商品管理',
icon: 'video-play',
url: 'Mall.vue'
}
],
token: Mock.Random.guid(),
message: '获取成功'
}
}
把获取的路由表存储到vuex中的menu,在vuex方法里面通过router.addRoute添加子路由
let menu=[]
const menuArray = []
menu.forEach(item => {
if (item.children) {
item.children = item.children.map(item => {
item.component = () => import(`../views/${item.url}`)
return item
})
menuArray.push(...item.children)
} else {
item.component = () => import(`../views/${item.url}`)
menuArray.push(item)
}
});
// 路由的动态添加子路由
menuArray.forEach(item => {
router.addRoute('Main', item)
})
},
4.按钮权限
所谓的按钮权限是指在某个菜单的界面中,我们需要根据后端返回的该角色当前操作模块中对应的按钮权限数据,展示出可进行操作的按钮,比如删除,修改,增加等按钮.
方法实现:
1.用v-if根据路由表里的meta.btnUse权限判断是否为true
2.通过自定义指令进行按钮权限的判断
//后台返回路由表的权限
menu: [
{
path: '/home',
name: 'home',
label: '首页',
icon: 's-home',
url: 'Home.vue'
meta: {
btnPermissions: ['add', 'edit', 'delete']
},
},
{
path: '/video',
name: 'video',
label: '商品管理',
icon: 'video-play',
url: 'Mall.vue'
meta: {
btnPermissions: ['add']
},
}
],
自定义权限指令
import Vue from 'vue'
/**权限指令**/
const btnPermission = Vue.directive('btnPermission', {
bind: function (el, binding, vnode) {
// 获取页面按钮权限
let btnPermissionsArr = [];
if(binding.value){
// 如果指令传值,获取指令参数,根据指令参数和当前登录人按钮权限做比较。
btnPermissionsArr = Array.of(binding.value);
}else{
// 否则获取路由中的参数,根据路由的btnPermissionsArr和当前登录人按钮权限做比较。
btnPermissionsArr = vnode.context.$route.meta.btnPermissions;
}
if (!Vue.prototype.$_has(btnPermissionsArr)) {
el.parentNode.removeChild(el);
}
}
});
// 权限检查方法
Vue.prototype.$_btnPermission = function (value) {
let isExist = false;
// 获取用户按钮权限
let btnPermissionsStr = sessionStorage.getItem("btnPermissions");
if (btnPermissionsStr == undefined || btnPermissionsStr == null) {
return false;
}
if (value.indexOf(btnPermissionsStr) > -1) {
isExist = true;
}
return isExist;
};
export {btnPermission}
组件中使用
<el-button @click='editClick' type="primary" v-btnPermission>添加</el-button>
5.数据权限
不同用户登录后,根据不同的用户信息后台返回不同的数据,例如:图表,个人财务数据信息等,只能显示自己的相关行数据
代码实现:
在axios请求头中携带用户相应信息,比如token;后端则通过用户身份令牌返回数据行