先后端分离下前端权限处理

权限在我看来指的是某个用户是否可以访问某个接口。对应到前端,即便某个用户访问了一个本不该该让他看到的页面,在访问接口时不具有权限,这样即便进入了页面,也不能看到相应的数据。可是咱们前端要作的工做就是让用户在访问这个页面的时候,直接就收到提示,没有权限。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

相关文章
相关标签/搜索