引言
本文章为基于Umi4的后台管理系统考虑的权限管理方案
在开发后台管理系统的过程中,我们不可避免的会涉及到权限管理。比如超管可以访问到所有的界面,某些用户只能访问到指定的页面
方法一 前端本地配置权限
步骤
-
打开权限管理插件
Umi4 中自带了权限管理的插件,我们只需要在
.umirc.ts文件中打开access项配置即可import { defineConfig } from '@umijs/max'; export default defineConfig({ access: {}, // 必须配置此项 // ... }) -
配置自定义的权限
在
src目录下新建access.ts文件,配置自定义的权限export default (initialState: any) => { // 在这里按照初始化数据定义项目中的权限,统一管理 // 参考文档 https://umijs.org/docs/max/access const { routes = {} } = initialState; // 从后端请求的routes const canSeeSuperAdmin = initialState && initialState?.currentUser?.isSuperAdmin; return { canSeeSuperAdmin, normalRouteFilter: (route: any) => Object.keys(routes).includes(route.name), }; }; -
为对应页面增加权限校验
我们需要在
.umirc.ts文件中的路由选项中加入access配置项import { defineConfig } from '@umijs/max'; export default defineConfig({ access: {}, routes: [ { name: '首页', path: '/home', component: '@/pages/Home', icon: 'HomeOutlined', access: 'normalRouteFilter', }, { name: '用户管理', path: '/userManage', component: '@/pages/UserManage', icon: 'UserOutlined', access: 'canSeeSuperAdmin', }, ] -
为指定页面的特定内容进行权限校验
Umi4提供了
useAcess()为权限管理的Hooks函数,并且可以使用Acess组件来包裹指定权限下才可显示的TSX元素Acess组件对应的属性如下:
- accessible (boolean) :是否有权限
- fallback (React.ReactNode) :无权限时的显示,默认无权限不显示任何内容
- children (React.ReactNode) :有权限时的显示
import React from 'react'; import { useAccess, Acess } from '@umijs/max'; import { Button } fronm 'antd'; const PageA = (props) => { const { foo } = props; const access = useAccess(); if (access.canReadFoo) { // 如果可以读取 Foo,则... } return ( <div> <Acess accessible={access.canSeeSuperAdmin} > <Button>Create</Button> </Acess> TODO </div> ); }; export default PageA;
优点
- 前端可以直接配置路由权限,配置简单
缺点
- 页面标题修改较为繁琐,需要前后端共同修改
- 用户不能灵活配置对应角色组的权限
方法二 前端渲染后端传回的动态路由
此处我们使用了Umi中的运行时配置文件,即app.tsx文件。我们需要在该文件导出patchClientRoutes函数,去修改我们现有的路由
步骤
动态路由在app.tsx中配置即可
import { requestAccountGetRoutes } from '@/utils/Account'
let extraRoutes: any[] = [];
// 配置routes
export const patchClientRoutes = ({ routes }) => {
// 直接修改routes即可,无需返回
}
// 获取routes数据
export const render = (oldRender) => {
requestAccountGetRoutes().then((res: any) => {
extraRoutes = JSON.parse(res.data)
console.log('=====routes======', extraRoutes);
oldRender()
})
}
优点
- 可以灵活配置各个角色的权限,包括页面权限,以及页面下具体按钮的权限
- 后端可以灵活配置页面的标题
缺点
- 后端同学工作量较大,权限配置较为繁琐