基于角色的访问控制并根据不同的场景显示不同的反馈信息

要实现基于角色的访问控制(RBAC),并根据不同的场景(如菜单项、页面、组件)显示不同的反馈信息(如隐藏、禁用、提示等),可以设计一套完整的解决方案。这个方案需要结合权限管理、上下文、路由控制和条件渲染等多个方面。以下是一个详细的实现方案:

1. 设置角色和权限

首先,定义你的角色和权限:

const roles = {
  ADMIN: 'admin',
  EDITOR: 'editor',
  VIEWER: 'viewer',
};

const permissions = {
  READ: 'read',
  WRITE: 'write',
  DELETE: 'delete',
};

const rolePermissions = {
  [roles.ADMIN]: [permissions.READ, permissions.WRITE, permissions.DELETE],
  [roles.EDITOR]: [permissions.READ, permissions.WRITE],
  [roles.VIEWER]: [permissions.READ],
};

2. 权限上下文

创建权限上下文,用于在整个应用中共享当前用户的角色和权限信息:

import React, { createContext, useContext } from 'react';

const PermissionsContext = createContext();

export const PermissionsProvider = ({ currentUser, children }) => {
  return (
    <PermissionsContext.Provider value={currentUser}>
      {children}
    </PermissionsContext.Provider>
  );
};

export const usePermissions = () => {
  return useContext(PermissionsContext);
};

3. 创建权限检查函数

实现一个函数,用于检查当前用户是否具有特定权限:

const hasPermission = (role, requiredPermission) => {
  const userPermissions = rolePermissions[role] || [];
  return userPermissions.includes(requiredPermission);
};

4. 创建高阶组件和组合组件

实现一个高阶组件(HOC)和组合组件,用于权限控制:

高阶组件(HOC)

import React from 'react';
import { usePermissions } from './PermissionsContext';

const withAuthorization = (WrappedComponent, requiredPermission) => {
  return (props) => {
    const currentUser = usePermissions();
    const userRole = currentUser.role;

    if (hasPermission(userRole, requiredPermission)) {
      return <WrappedComponent {...props} />;
    } else {
      return <div>Access Denied</div>; // 或者返回其他组件如 <Redirect />
    }
  };
};

export default withAuthorization;

组合组件

import React from 'react';
import { usePermissions } from './PermissionsContext';

const WithAuthorization = ({ requiredPermission, children, fallback }) => {
  const currentUser = usePermissions();
  const userRole = currentUser.role;

  if (hasPermission(userRole, requiredPermission)) {
    return children;
  } else {
    return fallback || <div>Access Denied</div>;
  }
};

export default WithAuthorization;

5. 路由控制

使用 ProtectedRoute 组件控制路由访问:

import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { usePermissions } from './PermissionsContext';

const ProtectedRoute = ({ component: Component, requiredPermission, ...rest }) => {
  const currentUser = usePermissions();
  const userRole = currentUser.role;

  return (
    <Route
      {...rest}
      render={(props) =>
        hasPermission(userRole, requiredPermission) ? (
          <Component {...props} />
        ) : (
          <Redirect to="/unauthorized" /> // 或者重定向到 404 页面
        )
      }
    />
  );
};

export default ProtectedRoute;

6. 菜单控制

根据权限动态生成菜单:

import React from 'react';
import { usePermissions } from './PermissionsContext';
import { Link } from 'react-router-dom';

const Menu = () => {
  const currentUser = usePermissions();
  const userRole = currentUser.role;

  return (
    <nav>
      <ul>
        {hasPermission(userRole, permissions.READ) && (
          <li>
            <Link to="/dashboard">Dashboard</Link>
          </li>
        )}
        {hasPermission(userRole, permissions.WRITE) && (
          <li>
            <Link to="/editor">Editor</Link>
          </li>
        )}
        {hasPermission(userRole, permissions.DELETE) && (
          <li>
            <Link to="/admin">Admin</Link>
          </li>
        )}
      </ul>
    </nav>
  );
};

export default Menu;

7. 组件内权限控制

在组件内使用组合组件进行权限控制:

import React from 'react';
import WithAuthorization from './WithAuthorization';

const AdminComponent = () => {
  return <div>Admin Content</div>;
};

const App = () => {
  return (
    <PermissionsProvider currentUser={{ role: roles.EDITOR }}>
      <div>
        <h1>My App</h1>
        <Menu />
        <WithAuthorization requiredPermission={permissions.DELETE} fallback={<div>Access Denied</div>}>
          <AdminComponent />
        </WithAuthorization>
      </div>
    </PermissionsProvider>
  );
};

export default App;

8. 显示不同的反馈信息

根据不同的场景显示不同的反馈信息:

import React from 'react';
import WithAuthorization from './WithAuthorization';

const DisabledButton = () => <button disabled>You don't have permission</button>;

const AdminComponent = () => {
  return <div>Admin Content</div>;
};

const App = () => {
  return (
    <PermissionsProvider currentUser={{ role: roles.VIEWER }}>
      <div>
        <h1>My App</h1>
        <Menu />
        <WithAuthorization requiredPermission={permissions.DELETE} fallback={<DisabledButton />}>
          <AdminComponent />
        </WithAuthorization>
      </div>
    </PermissionsProvider>
  );
};

export default App;

总结

通过上述步骤,可以实现一套完整的基于 RBAC 的权限控制方案,涵盖了菜单项、页面访问、组件显示等不同场景的权限控制。组合方式和高阶组件(HOC)各有优势,可以根据实际需求灵活使用。通过权限上下文、权限检查函数、高阶组件和组合组件,可以确保权限控制逻辑的复用性和灵活性,使得权限管理更加简洁和高效。

posted @ 2024-05-14 12:37  让速不让路  阅读(24)  评论(0编辑  收藏  举报