我的编程空间,编程开发者的网络收藏夹
学习永远不晚

React 组件权限控制的实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

React 组件权限控制的实现

前话

具备用户体系的业务系统往往需要具备权限控制的能力。前后不分离的开发模式权限控制主要由后端结合模版引擎实现,而前后分离的开发模式由前后两端协商权限配置分别进行数据权限控制和组件权限控制。

正文

权限配置格式不限,为进行后续演示本篇设定权限配置如下:

export type IAuthConfig = {
  
  keys: string[];
};

且提供一个Hook直接获取当前用户信息:

export type IUser = {
  
  authConfig: IAuthConfig;
};


export function useUser() {
  // ...略
  return user;
}

首先我们先定义一个权限Hook,内容如下:


function getAuthKeys(auth: string | string[]) {
  return Array.isArray(auth) ? auth : [auth];
}


export enum EAuthType {
  
  "some" = "some",
  
  "every" = "every",
}


export function useAuth() {
  const { authConfig } = useUser();

  // 权限标识列表
  const authKeys = useMemo(() => authConfig?.keys ?? [], [authConfig]);
  // 校验是否具备权限
  const hasAuth = useCallback(
    (auth: string | string[], type?: EAuthType) =>
      getAuthKeys(auth)[type ?? EAuthType.every]((key) =>
        authKeys.includes(key)
      ),
    [authKeys]
  );

  const ret: [typeof authKeys, typeof hasAuth] = [authKeys, hasAuth];
  return ret;
}

1. 控制方式

对于前端开发而言一般只需做组件控制,控制方式有很多种写法。

1.1 直接计算

const Cmpt: React.FC = () => {
  const [, hasAuth] = useAuth();
  // 计算是否有权限
  const authorized = useMemo(() => hasAuth("test"), [hasAuth]);

  // ...略
};

1.2 通用权限Hoc

export function withAuth<P extends Record<string, unknown> = {}>(
  auth: string | string[],
  type?: EAuthType
) {
  return function (Component: any) {
    const WrappedComponent: React.FC<P> = (props) => {
      const [, hasAuth] = useAuth();

      const instance = React.createElement(Component, {
        ...props,
      });

      // 计算是否有权限
      const authorized = hasAuth(auth, type);

      // ...略
    };

    WrappedComponent.displayName = `withAuth(${getDisplayName(Component)})`;

    return WrappedComponent;
  };
}

1.3 权限包裹组件

const AuthWrapper: React.FC<IProps> = ({ auth, type, children }) => {
  const [, hasAuth] = useAuth();
  // 计算是否有权限
  const authorized = useMemo(() => hasAuth(auth, type), [auth, type, hasAuth]);

  // ...略
};

2. 控制结果

常见控制结果为控制组件的显示或隐藏,或根据是否具备权限做组件的自定义渲染。

为方便演示后面统一使用权限包裹组件进行说明。

2.1 显隐控制

具备权限的组件直接渲染,否则返回null,即可实现显隐控制。权限包裹组件实现如下:

const AuthWrapper: React.FC<IProps> = ({ auth, type, children }) => {
  const [, hasAuth] = useAuth();
  // 计算是否有权限
  const authorized = useMemo(() => hasAuth(auth, type), [auth, type, hasAuth]);
  // 具备权限的组件直接渲染,否则返回null
  return authorized ? children : null;
};

在需要权限控制的组件外包裹权限组件即可。

const Cmpt: React.FC = () => {
  <>
    <AuthWrapper auth="test">
      <Button>Hello World</Button>
    </AuthWrapper>
  </>;
};

2.2 自定义渲染

实际业务场景中,存在需要提醒用户没有权限的情况,这时需要权限包裹组件支持自定义渲染,实现方式有多种:

  • 静态props注入
  • 动态props映射
  • render props

相比较之下render props更为自由,权限包裹组件完善后实现如下:

type IProps = {
  
  auth: string | string[];
  
  type?: EAuthType;
  
};

const AuthWrapper: React.FC<IProps> = ({ auth, type, children }) => {
  const [, hasAuth] = useAuth();
  // 计算是否有权限
  const authorized = useMemo(() => hasAuth(auth, type), [auth, type, hasAuth]);

  // 自定义渲染
  if (typeof children === "function") {
    return children(authorized);
  }

  // 显隐控制
  return authorized ? children : null;
};

这时就可以渲染提示无权限组件:

const Cmpt: React.FC = () => {
  <>
    <AuthWrapper auth="test">
      {(authorized) => <Button disabled={!authorized}>Hello World</Button>}
    </AuthWrapper>
  </>;
};

3. 权限数据

前端开发做组件控制的颗粒度取决于权限数据的类型,权限数据类型分为静态权限和动态权限。
其中静态权限一般在完成登录认证后即可一次性获取,而动态权限则在操作数据时进行权限校验。
因此不难发现静态权限往往用于控制路由、页面或者粗糙的操作权限。而动态权限则能够对动态数据进行更细粒度的操作权限控制(需后端数据权限控制能力配合)。

3.1 静态权限

如前面描述,登录认证后即可从用户信息中得到权限标识,同样前面的栗子均也为静态权限示例。

3.2 动态权限

需要动态权限校验的场景在业务系统中也较为常见,例如用户能够看到列表数据,但禁止查阅无权限的数据详情。
由此可知对于用户而言,获取的动态的列表数据需要逐一进行权限校验,这时我们对权限Hook和包裹组件进行改造,改造后代码如下:

type IAuthDynamicConfig = {
  // ...略
};


export function useAuth() {
  // ...略

  // 动态校验是否具有权限
  const dynamicAuth = useCallback(
    (auth: string | string[], type?: EAuthType, config?: IAuthDynamicConfig) =>
      // 批量异步校验权限,实现略
      append2DynamicAuthTask(auth, type, config),
    []
  );

  const ret: [typeof authKeys, typeof hasAuth, typeof dynamicAuth] = [
    authKeys,
    hasAuth,
    dynamicAuth,
  ];
  return ret;
}


const AuthWrapper: React.FC<IProps> = ({ auth, type, config, children }) => {
  const [, hasAuth, dynamicAuth] = useAuth();

  const [authorized, setAuthorized] = useState(false);

  // 计算是否有权限
  useEffect(() => {
    if (config === undefined) {
      setAuthorized(hasAuth(auth, type));
      return;
    }
    dynamicAuth(auth, type, config).then(setAuthorized);
  }, [auth, type, config, hasAuth, dynamicAuth]);

  // ...略
};

使用方式如下:

const Cmpt: React.FC = () => {
  // ...略

  <>
    {data.map((item) => (
      <div key={item.id}>
        <div>{item.title}</div>
        <div>
          <AuthWrapper
            auth="detail"
            config={{
              module: "demo",
              identify: item.id,
            }}
          >
            {(authorized) => (
              <Button disabled={!authorized} onClick={handleDetail}>
                详情
              </Button>
            )}
          </AuthWrapper>
        </div>
      </div>
    ))}
  </>;
};

到此这篇关于React 组件权限控制的实现的文章就介绍到这了,更多相关React 组件权限控制内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

React 组件权限控制的实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

React-Router(V6)的权限控制实现示例

本文主要介绍了React-Router(V6)的权限控制实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-19

vue-router如何实现权限控制

这篇文章主要讲解了“vue-router如何实现权限控制”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue-router如何实现权限控制”吧!在vue-router控制前端权限是常见需求:
2023-07-04

Openresty如何实现的网关权限控制

小编给大家分享一下Openresty如何实现的网关权限控制,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!技术栈本小节采用了以下的技术栈:Openresty(lua
2023-06-19

vue如何实现路由权限控制

这篇“vue如何实现路由权限控制”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“vue如何实现路由权限控制”文章吧。在Vue中
2023-07-06

CentOS下如何实现ACL权限控制

这篇文章主要介绍“CentOS下如何实现ACL权限控制”,在日常操作中,相信很多人在CentOS下如何实现ACL权限控制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”CentOS下如何实现ACL权限控制”的疑
2023-06-10

vue按钮怎么实现权限控制

这篇文章主要讲解了“vue按钮怎么实现权限控制”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue按钮怎么实现权限控制”吧!一、步骤1.定义buttom权限在state中创建buttomPe
2023-06-22

React如何使用高阶组件与Hooks实现权限拦截

本篇内容主要讲解“React如何使用高阶组件与Hooks实现权限拦截”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“React如何使用高阶组件与Hooks实现权限拦截”吧!高阶组件是以组件作为参数
2023-07-05

阿里云OSS访问权限配置(RAM权限控制)实现

场景 需要将阿里云oss的某个bucket的指定目录授权给测试人员使用,比如指定 myBuket 的 static/material/ 目录。 测试人员通过ossbrowser工具来维护这个目录。步骤 新建用户 在RAM访问控制中新
2022-06-04

Spring Security权限控制的接口怎么实现

本篇内容主要讲解“Spring Security权限控制的接口怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring Security权限控制的接口怎么实现”吧!Introducti
2023-07-05

编程热搜

目录