利用umi插件快速实现权限控制

简介: 本文介绍在umijs3中如何利用内置插件快速集成权限管理功能。

umi3内置了@umijs/plugin-access可以快速实现精细的权限控制功能,本文将会实现页面级的权限功能,并给出实现代码。

本文使用的的umi版本为3.x。

关于 @umijs/plugin-access

有 src/access.ts 时启用。

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

按照文档,我们将实现一个可读权限,没有权限时显示404页面。

// src/access.ts
export default function (initialState) {
  const { userInfo } = initialState;

  return {
   read: userInfo.userName === 'abc',
  };
}

关于 @umijs/plugin-initial-state

上面代码中的initialState来源于另一个插件@umijs/plugin-initial-state:

有 src/app.ts 并且导出 getInitialState 方法时启用。

按文档说明,添加如下配置:

export function getInitialState() {
  return new Promise((resolve) => {
    // 模拟 api请求获取用户信息
    setTimeout(
    () => {
        resolve({
        userInfo: { userName: 'abc' },
      });
    }, 500);
   });
}

正常情况下,应该可以在src/.umi目录下看到生成的plugin-initial-state和plugin-access目录,表示我们成功启用了这两个插件。

代码中使用

全局设置

一般umi项目中会有一个全局的布局文件 src/layouts/index.ts,里面组件的props.children为当前路由需要渲染的页面,我们可以在这里对权限进行判断,没有权限时显示404页面:

import NotFound from '@/pages/404';
import { useAccess } from 'umi';

const { children } = props;
const access = useAccess();
const authChildren = access.read ? children : <NotFound />;
 

把要渲染的组件换成authChildren即可。

其他页面设置

@umijs/plugin-access还提供了Access组件:

import { useAccess, Access } from 'umi';
import NotFound from '@/pages/404';

const EditPage = props => {

  const access = useAccess(); 
 
  return (
    <div>
      <Access
        accessible={access.write}
        fallback={<NotFound />}
      >
        Edit page
      </Access>
    </div>
  );
};

其他

这部分主要讲讲实践中遇到的问题以及解决方法。

与dva状态同步

我们一般会把用户信息存放在dva model中,如果我们在getInitialState中调用了获取了用户信息的方法,我们可以同步到dva model中,省去了在dva中触发effect再调用一次相同的接口:

// src/access.ts
import { getDvaApp } from 'umi';

export default function (initialState) {
  const { userInfo } = initialState;

  // 触发reducer
  getDvaApp()._store.dispatch({ type: 'common/update', userInfo });
  
  return {
   read: userInfo.userName === 'abc',
  };
}

如何动态修改access中的值?

翻一下插件生成的代码找找思路:

// src/.umi/plugin-access/AccessProvider.ts
  const { initialState } = useModel('@@initialState');

  const access: AccessInstance = useMemo(() => accessFactory(initialState as any), [initialState]);

  return React.createElement(
    AccessContext.Provider,
    { value: access },
    React.cloneElement(children, {
      ...children.props,
      routes:traverseModifyRoutes(props.routes, access)
    }),
  );

可以看到,只是在根元素外面套了一层context,而我们要动态修改的,是这个access的值。它在一个useMemo中返回, 因此我们要修改access,只需修改initalState即可。

而修改initalState的方法很简单:

import { useModel } from 'umi';

const { initialState, setInitialState } = useModel('@@initialState');

setInitialState({ ...initialState, userInfo: { userName: 'newUser' } });

即可触发access的修改, 重新执行src/access.ts中的逻辑。

目录
相关文章
|
负载均衡 应用服务中间件 API
Nginx、Kong、Apisix、Gateway网关比较
Nginx、Kong、Apisix、Gateway网关比较
6793 1
Nginx、Kong、Apisix、Gateway网关比较
|
JavaScript
【JS用法】js判断字符串是否包含某个字符串
【JS用法】js判断字符串是否包含某个字符串
1129 0
|
4月前
|
JavaScript 定位技术 API
CodeGraph 爆火:编程 Agent 需要的不是更多上下文,而是一张提前画好的代码地图
CodeGraph 是一款爆火的本地代码智能工具,通过 tree-sitter 解析 AST 构建结构化知识图谱(存于 SQLite),为编程 Agent 提前生成“代码地图”。它显著降低 Agent 在中大型项目中的探索成本——实测工具调用减少71%、Token 降57%、速度提升46%,支持19+语言及主流框架路由识别,完全离线、无需 API Key。
1702 12
CodeGraph 爆火:编程 Agent 需要的不是更多上下文,而是一张提前画好的代码地图
|
7月前
|
存储 人工智能 搜索推荐
阿里云AI Agent 搭建全套餐费用价格及使用教程(qwen-plus+函数计算CU+NAS资源包)
阿里云AI Agent搭建全套餐仅113.66元,含Qwen-Plus大模型(12000千tokens)、函数计算CU包(50万CU)及NAS存储(200GiB),覆盖LangStudio推理、MCP搜索与文档持久化需求,资源自动抵扣,性价比高。
748 2
|
存储 开发工具 git
|
自然语言处理 测试技术 API
TCPDF库详解:功能、作用及多语言安装指南-tcpdf可不是只有php能用-优雅草卓伊凡
TCPDF库详解:功能、作用及多语言安装指南-tcpdf可不是只有php能用-优雅草卓伊凡
920 5
|
Java
Java aop 如何获取请求头里的token
【8月更文挑战第13天】Java aop 如何获取请求头里的token
536 0
|
JavaScript 前端开发 安全
|
存储 索引
antd中table组件选中单行换样式(比如背景颜色)
在Ant Design (antd)的Table组件中,可以通过设置`onRow`属性来定义行点击事件,从而改变被点击行的样式,如背景颜色。`onRow`是一个函数,返回一个对象,对象包含事件处理函数,如`onClick`。同时,使用`rowClassName`属性来指定行的类名,结合状态管理,可以实现点击某行后改变其背景颜色的效果。具体实现时,需要在组件状态中保存当前被点击行的索引,然后通过`rowClassName`判断并返回相应的类名。
2031 2
antd中table组件选中单行换样式(比如背景颜色)