权限控制
权限控制是中后台系统中常见的需求之一,你可以利用我们提供的 路由权限
和 指令权限
,实现一些基本的权限控制功能,IBPS平台中也包含了几个简单示例以提供参考
一、路由和默认权限控制
IBPS平台 提供了两套权限实现方案:
- 方案一:前端固定路由表和权限配置,由后端提供用户权限标识,来识别是否拥有该路由权限。
- 方案二:后端提供权限和路由信息结构接口,动态生成权限和菜单。
1.1、方案一:前端固定路由表和权限配置方案
步骤如下:
判断是否有
Token
如果没有则跳转到登录页面如果有
Token
获取用户信息和拥有权限store.dispatch('ibps/user/load')
用户信息获取成功后, 调用菜单初始数据
store.dispatch('ibps/menu/init')
根据获取到的用户信息构建出一个已经过滤好权限的路由结构(@/router/utils.js
)将构建的路由结构信息利用
Vue-Router
提供的动态增加路由方法router.addRoute
加入到路由表中(说明:vue-router 3.5.0+版本采用router.addRoute
替换【下同】)router.addRoutes
加入路由表后将页面跳转到用户原始要访问的页面,如果没有 redirect 则进入默认页面 (/dashboard)
这里可以看出把登录
和获取用户信息
分成了两个接口,主要目的在于当用户刷新页面时,可以根据登录时获取到的身份令牌(cookie/token
)等,去获取用户信息,从而避免刷新需要调用登录接口
IBPS平台 实现的路由权限的控制代码都在
@/router/index.js
中,如果想修改逻辑,直接在适当的判断逻辑中next()
释放钩子即可。
两套权限实现 均使用@/router/index.js
(路由守卫)来进行控制。
1.2、方案二:动态权限(平台默认方案)
但其实很多公司的业务逻辑可能并不是上面描述的简单实现方案,比如正常业务逻辑下 每个页面的信息都是动态从后端配置的,并不是像 默认的路由表那样写死在预设的。你可以在后台通过一个 tree 或者其它展现形式给每一个页面动态配置权限,之后将这份路由表存储到后端。
权限/菜单 eg:
角色 eg:
由 角色关联 到多个 权限(菜单) 。 角色
1 对多
权限,用户1 对多
角色 (或 用户1 对 1
角色);
当用户登录后得到 用户信息,前端根据 用户信息 去向后端请求可访问的路由表,从而动态生成可访问页面,之后就是 router.addRoutes
动态挂载到 router 上,你会发现原来是相同的,万变不离其宗。
eg:// 后端返回的 JSON 动态路由结构
// 生成路由代码 @/router/utils.js
以下截取部分
/**
* 构建子路由
* @param {*} menus
*/
function generateSubRoutes(menus) {
const pool = []
const push = function(menus, namePrefix = []) {
menus.forEach(menu => {
const router = {
id: menu[idKey],
parentId: menu[parentIdKey],
path: [...namePrefix, menu[nameKey]].join('/'),
name: [...namePrefix, menu[nameKey]].join('-'),
alias: defaultRouterAlias + menu[nameKey],
component: getComputedUrl(menu[urlKey]),
// hidden: menu[displayInMenuKey] === 'N',
meta: {
title: menu[labelKey],
icon: menu[iconKey] || 'file-o',
name: menu[nameKey],
defaultUrl: menu[urlKey],
...meta
}
}
if (menu[childrenKey] && menu[childrenKey].length > 0) {
if (menu[urlKey]) {
pool.push({
...router
})
}
push(menu[childrenKey], [...namePrefix, menu[nameKey]])
} else {
pool.push({
...router
})
}
})
}
push(menus)
return pool
}
二、指令权限
IBPS平台 封装了一个非常方便实现按钮级别权限的自定义指令。v-permission
使用
<!-- eg: 当前页面为 dashboard -->
<template>
<!-- 校验是否有 dashboard 权限下的 add 操作权限 -->
<a-button v-permission="add" >添加用户</a-button>
<!-- 校验是否有 dashboard 权限下的 del 操作权限 -->
<a-button v-permission="del">删除用户</a-button>
<!-- 校验是否有 dashboard 权限下的 edit 操作权限 -->
<a v-permission="edit" @click="edit(record)">修改</a>
</template>
需要注意的是,指令权限默认从 store 中获取当前已经登陆的用户的角色和权限信息进行比对,所以也要对指令权限的获取和校验 Action 权限部分进行自定义。
其中在数据模版中 权限key
ibps_data_template_tpl_+模板key+_+按钮key
在某些情况下,不适合使用 v-permission
,例如 Tab 组件,只能通过手动设置v-if
来实现。或者disabled 属性进行禁用
这时候,IBPS平台为其提供了原始v-if
级别的权限判断。
以上代码的 if 判断会检查,当前登录用户是否存在 dashboard 下的 add / del / edit 权限
实现思路:
在 Vue 初始化时,@/plugins/permission.js 作为插件注册到 Vue 原型链上,在 Vue 实例中就可以用 this.$auth()
方法进行权限判断。 当然这里也要对权限的获取和校验 Action 权限部分进行自定义。