权限在我看来指的是某个用户是否可以访问某个接口。对应到前端,即便某个用户访问了一个本不该该让他看到的页面,在访问接口时不具有权限,这样即便进入了页面,也不能看到相应的数据。可是咱们前端要作的工做就是让用户在访问这个页面的时候,直接就收到提示,没有权限。javascript
但如今许多项目中页面路由都是由前端去管理了,如何作到这一点呢,接下来我就分享一下在过往项目中我所用的方案。前端
我写了demo,上传到了github上,地址为:admin-permission-demovue
一开始与后端去对接这个需求的时候,我是感到很懵逼的,以为无从下手。由于我根本就不知道权限控制是怎么去作的,也不知道权限其实就是限制用户对于接口的访问。因此开始以前我以为有必要说一下,权限表是怎样设计的。 咱们项目中所使用的是 RBAC ,其实很简单,就是有这么三个东西:用户、角色、权限(资源)。图我就懒得画了,省事儿直接用一个别人画好的图。java
这个权限就是项目中的接口,意思就很明显了。给角色规定了可以访问哪些接口,而后给用户分配了角色。这样就能控制用户哪些接口能访问,哪些接口不能访问。react
咱们项目中权限表的大概的样子:git
id | p_id | type | permission | name |
---|---|---|---|---|
主键ID | 父级ID | 类型:菜单或按钮 | 权限标识 | 名称 |
权限又分为菜单权限和按钮权限,什么意思呢?github
比方说咱们如今要开发一个页面,叫作用户管理,在用户管理这个页面会进行一些对用户增删查改的操做。我管这个用户管理叫作菜单权限,它下面的增删查改(接口)的操做叫作按钮权限。这些接口的p_id很显然就是这个菜单权限的主键ID了。typescript
[
{
p_id: '',
id: 1000,
name: '权限管理',
type: 1, // 菜单
permission: 'permission_manage',
children: [
{
p_id: 1000,
id: 1100,
name: '用户管理',
type: 1, // 菜单
permission: 'user_manage',
children: [
{
p_id: 110,
id: 1101,
name: '添加用户',
type: 2, // 按钮
}
...
]
}
]
}
]
复制代码
怎么样,这样的数据结构是否是很熟悉,是否是就是管理系统中左侧菜单。这个 菜单权限,就是前端在作页面访问控制时所要用到的东西。这个数据结构只是我为了方便理解这样写的。 在个人项目中我向后端查询到的权限数据不长这个样子,就是一个数组,每一项是数据,没有作分组操做(就是没有children)。这样前端拿到数据了以后就能够根据 type
去整合成菜单权限集合和按钮权限集合,方便了后续的使用。数据库
理解了权限是怎么设计的,接下来讲说前端代码怎么去实现。redux
我过往的项目中所使用的都是 react + antd + dva + typescript。其实前端所选用的技术是什么并不重要,重要的是思路理解了,剩下的只是代码实现的不一样。
首先我会要后端给我提供一个接口,查询当前用户的全部权限。而后我会把它分为 菜单权限 和 按钮权限 用 redux
去管理。
首先是渲染左侧菜单。在项目中通常状况下会有一个专门的左侧菜单的配置文件,在该文件里定义了菜单的名字啊、图标啊、页面路径等信息。有些菜单页面是须要被权限管理的,而有些则不须要。对于须要被权限管理的页面我会添加一个字段叫作菜单标识。
interface MenuDataItem {
name: string; // 菜单名字
icon?: string;
path: string;
children?: Array<MenuDataItem>;
permission?: string; // 菜单标识
}
const menuData: MenuDataItem[] = [...];
复制代码
项目中的左侧菜单,就会根据这个 menuData
被渲染出来。这里的逻辑是首先看这个菜单有没有菜单标识,若是没有的话直接渲染。若是有菜单标识的话,就看用户是否具备这个菜单权限,有就渲染,没有就不渲染。每一个项目的结构确定不一样,我就很少贴代码了,重要的是思路,具体实现我写了demo,传到了github上,感兴趣能够去看,这是地址:admin-permission-demo。
只管理了左侧菜单的渲染确定是不够的,须要在路由层面再去作控制。通常状况下项目中会有一份路由表,react
的话路由也是组件,在路由渲染的地方去作控制就行。vue
的话是全局配置 router
的,在路由守卫中限制就行。一样的,页面对应菜单路由,看用户是否具备菜单权限,不具有就到提示权限不够页面,具有就正常显示页面。
仍是拿用户管理来举一个例子,增、删、查、改。 可能用户只具有 删、查、改的权限而不具有增的权限。这时候在页面中就不该该渲染 “添加用户” 这样的按钮了,否则用户数据输入了半天,一发请求后端一校验提示权限不足就尴尬了,我都不能作这个操做,你还展示给我干啥?
这时候去写一个组件,叫啥不重要,就好比说叫 PermissionButton
把。react的话将本来按钮做为 children 传入该组件,vue 的话应该就是 <slot>
。而后该组件还接收一个 props
,它是一个数组,就叫他 permissions
把。该数组的每一项就是按钮权限标识,表明须要哪些权限才能展现这个按钮,或者也有可能具备其中一项就能够展现。在提供一个props
去控制把,值为 every 或者 some。every就是全都有才能展现,some就是具有其中一项就能展现。
而后就是去查用户的 按钮权限 了。 具有了改组件就展现 本来组件,不具有就不展现就好了。
这是我作后台管理系统所积累的一点实践把。若是你们有何更好的方案,或者以为哪里能够改进的欢迎交流。
对 vue 的用户可能不太友好。由于demo是react实现的。可是我并不以为这个方案在react和vue下有太大的差别。若是后面我在工做中有使用vue去作的机会,在更新一版使用vue的demo把。最重要的仍是要去理解这个权限,其实也是简单的东西。但愿可以帮助到有须要的人。
具体实现确定不是几行代码可以贴清楚的,代码怎么实现也关系到具体的项目结构。
我提供了demo,上传到了github上,地址为:admin-permission-demo。
demo也是根据我本身搭的管理系统模板作的,地址为:antd-admin