react 权限管制计划实际

权限管制是我的项目中,特地是后盾治理我的项目中比拟常见的性能了
结合实际的我的项目需要,讲讲在react中是如何实现权限管制的

背景

  1. 我的项目应用umi搭建
  2. 需要:

    1. 依据不同角色权限配置路由权限
    2. 依据不同权限管制页面显示成果
    3. 按钮显示暗藏

实现页面路由权限

实现成果:无权限的用户没有该页面的入口:左侧菜单无入口,以及间接进入url提醒无权限

@umijs/plugin-access

https://umijs.org/zh-CN/plugi...
配合@umijs/plugin-access 插件应用

src/access.ts

约定 src/access.ts 文件为权限定义文件,该文件须要默认导出一个办法,导出的办法会在我的项目初始化时被执行。该办法须要返回一个对象,对象的每一个值就对应定义了一条权限。具体的介绍见文档。

计划1

我的需要是依据用户角色来判断是否有该路由权限,如果依照文档的demo来,那么我须要先:

  1. 定义每个角色是否有pageA权限,pageB权限……
  2. 再在 access.ts 里输入对象 {canReadPageA: true, canReadPageB: false...}
  3. 而后再在路由文件里定义 access: 'canReadPageA', access: 'canReadPageB'……

这样尽管能够实现,但代码量太大,要对每个须要权限的页面进行定义和判断,access.ts 和 route.ts 文件都须要嵌入大量代码

所以我扭转了思路,换了另一种计划,也就是计划2

计划2

access.ts 中,当返回的对象中,值是办法时:

  1. 参数是route, 即是以后路由信息
  2. 办法最初返回布尔值

利用这个参数,就能够在 route 里退出咱们所须要的信息

// routes.ts[  {    name: 'pageA',    path: '/pageA',    component: './pageA',    access: 'auth', // 权限定义返回值的某个 key    roles: ['admin', 'user'], // role为admin或者user时能够拜访pageA页面  },  {    name: 'pageB',    path: '/pageB',    component: './pageB',    access: 'auth',    roles: ['admin'],// 只有role为admin时能够拜访pageA页面  },]

我给 route 配置了两个属性:

  1. access 值为 access.ts 返回对象的某个key,这里的话固定为 auth
  2. roles 定义能够有该页面权限的角色组

access.ts 中返回key为 auth 的对象:

// access.tslet hasAuth = (route: any, roleId?: string) => {  //  要害:比照route.roles 和 currentUser.roleId 判断是否有权限  return route.roles ? route.roles.includes(roleId) : true;};export default function access(initialState: { currentUser?: API.CurrentUser | undefined }) {  const { currentUser } = initialState || {};  return {    auth: (route: any) => hasAuth(route, currentUser?.roleId),  };}

拿到route里的信息和以后用户信息进行比照,判断,返回布尔值

比照计划1,计划2长处就是,之后新增页面时,只须要在 routes.ts 里定义好该页面的 accessroles 属性, 不须要改变到 access.ts

实现权限管制页面显示

实现成果:用户有菜单入口,进入页面后显示无权限

计划1

思路:

  1. 利用 umi 提供的 Access 组件来实现
  2. 依据 currentUser 对应的字段来判断是否有权限
    代码如下:

    import { Access } from 'umi';<Access accessible={currentUser.foo} fallback={<div>暂无权限</div>}>  Foo content.</Access>;

    毛病:须要在对应的页面中嵌入代码

计划2

思路:

通过高阶组件 wrappers 实现

  1. routes.ts 配置 wrappers 属性

    // routes.ts[  { name: 'pageA', path: '/pageA', component: './pageA', wrappers: ['@/wrappers/authA']  },  { name: 'pageB', path: '/pageB', component: './pageB', wrappers: ['@/wrappers/authB']  },]

    这样,拜访 /pageA 时,会先通过 @/wrappers/authA 做权限校验

  2. 而后在 @/wrappers/authA 中,
// wrappers/authAimport { useModel } from 'umi';export default (props) => {  const { initialState } = useModel('@@initialState');  const { currentUser } = initialState || {};  if (currentUser.authA) {    return <div>{ props.children }</div>;  } else {    return <div>无权限</div>;  }}

这样,依据 currentUser 来判断是否渲染组件

计划2的长处是:

毋庸在页面组件中嵌入相干代码,只须要在 routes.tx 中配置 wrappers ,鉴权局部由 @/wrappers/ 来解决

然而,毛病就是,如果有多个权限,如authA, authB, authC…… 那么则须要在 @/wrappers/ 新建多个鉴权文件

实现按钮权限

实现成果:
无权限的按钮不显示或者置灰

个别的做法是在组件中判断

// 不显示按钮{currentUser.auth ?  <button>创立</button> : null}// 置灰{<button disabled={currentUser.auth}>创立</button>}

但如果有大量的权限按钮,那么将要写好屡次这种代码,所以在这里对按钮进行一次封装

// AuthBtnimport React, { useState, useEffect, useRef } from 'react';import { Button } from 'antd';const AuthBtn: React.FC<{}> = (props) => {  let { authId, children } = props;  // btnIds 应该有后盾接口返回,通知前端用户有哪些按钮权限  let btnIds = ['read', 'edit'];  let hasAuth = btnIds.includes(authId);  // 这里能够依据理论需要封装  return <Button disabled={!hasAuth}>{children}</Button>;};export default AuthBtn;// index.ts<AuthBtn authId="read">read 只读权限</AuthBtn><AuthBtn authId="write">write 写入权限</AuthBtn>

传入的 authId 须要先和后盾约定好, 还能够依据理论需要传入type、loading等

这样,一般按钮用 Button, 须要鉴权的应用 AuthBtn

总结

以上就是最近对于权限管制的实际,做到对路由、页面和按钮层级进行鉴权,每一种都有对应的实现计划,每个计划都有本人的优缺点,旨在更优雅地编程!
如果有更好的计划,欢送评论区留言!