react 权限管制计划实际
权限管制是我的项目中,特地是后盾治理我的项目中比拟常见的性能了
结合实际的我的项目需要,讲讲在react中是如何实现权限管制的
背景
- 我的项目应用umi搭建
需要:
- 依据不同角色权限配置路由权限
- 依据不同权限管制页面显示成果
- 按钮显示暗藏
实现页面路由权限
实现成果:无权限的用户没有该页面的入口:左侧菜单无入口,以及间接进入url提醒无权限
@umijs/plugin-access
https://umijs.org/zh-CN/plugi...
配合@umijs/plugin-access
插件应用
src/access.ts
约定 src/access.ts
文件为权限定义文件,该文件须要默认导出一个办法,导出的办法会在我的项目初始化时被执行。该办法须要返回一个对象,对象的每一个值就对应定义了一条权限。具体的介绍见文档。
计划1
我的需要是依据用户角色来判断是否有该路由权限,如果依照文档的demo来,那么我须要先:
- 定义每个角色是否有pageA权限,pageB权限……
- 再在
access.ts
里输入对象{canReadPageA: true, canReadPageB: false...}
- 而后再在路由文件里定义
access: 'canReadPageA'
,access: 'canReadPageB'
……
这样尽管能够实现,但代码量太大,要对每个须要权限的页面进行定义和判断,access.ts 和 route.ts 文件都须要嵌入大量代码
所以我扭转了思路,换了另一种计划,也就是计划2
计划2
在 access.ts
中,当返回的对象中,值是办法时:
- 参数是route, 即是以后路由信息
- 办法最初返回布尔值
利用这个参数,就能够在 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 配置了两个属性:
access
值为access.ts
返回对象的某个key,这里的话固定为auth
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
里定义好该页面的 access
和 roles
属性, 不须要改变到 access.ts
实现权限管制页面显示
实现成果:用户有菜单入口,进入页面后显示无权限
计划1
思路:
- 利用 umi 提供的 Access 组件来实现
依据
currentUser
对应的字段来判断是否有权限
代码如下:import { Access } from 'umi';<Access accessible={currentUser.foo} fallback={<div>暂无权限</div>}> Foo content.</Access>;
毛病:须要在对应的页面中嵌入代码
计划2
思路:
通过高阶组件 wrappers
实现
在
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
做权限校验- 而后在
@/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
总结
以上就是最近对于权限管制的实际,做到对路由、页面和按钮层级进行鉴权,每一种都有对应的实现计划,每个计划都有本人的优缺点,旨在更优雅地编程!
如果有更好的计划,欢送评论区留言!