Rustzen Admin 前端简单权限系统设计与实现

这是一套完整的前端权限控制系统,基于 React + TypeScript + Zustand 技术栈构建。该系统实现了细粒度的权限控制,包括路由级权限、组件级权限和操作级权限,确保用户只能访问和操作其有权限的功能模块。具体代码请查看 Github Rustzen Admin Web

核心架构

1. 权限数据结构

系统采用基于字符串的权限码设计,权限码格式为 module:resource:action,例如:

  • system:user:create - 用户创建权限
  • system:user:edit - 用户编辑权限
  • system:user:delete - 用户删除权限
  • system:user:list - 用户列表查看权限
typescript 复制代码
interface UserInfoResponse {
  id: number;
  username: string;
  realName?: string;
  avatarUrl?: string;
  permissions: string[]; // 权限码数组
  isSystem: boolean; // 是否是系统管理员
}

2. 状态管理 - Zustand Store

权限状态通过 useAuthStore 进行集中管理,使用 Zustand 的 persist 中间件实现状态持久化:

typescript 复制代码
interface AuthState {
  userInfo: Auth.UserInfoResponse | null;
  token: string | null;
  updateUserInfo: (params: Auth.UserInfoResponse) => void;
  updateToken: (params: string) => void;
  setAuth: (params: Auth.LoginResponse) => void;
  clearAuth: () => void;
  checkPermissions: (code: string) => boolean;
  checkMenuPermissions: (path: string) => boolean;
}

权限验证机制

1. 权限码验证算法

系统实现了智能的权限码匹配,支持通配符和层级权限,具体实现如下:

typescript 复制代码
checkPermissions: (code: string) => {
  const permissions = get().userInfo?.permissions || [];
  if (permissions.length === 0) {
    return false;
  }
  if (permissions.includes("*")) {
    return true; // 超级管理员
  }
  if (permissions.includes(code)) {
    return true; // 精确匹配
  }
  // 层级权限匹配:system:user:* -> system:*
  const codeArr = code.split(":");
  for (let i = codeArr.length - 1; i > 0; i--) {
    const prefix = codeArr.slice(0, i).join(":") + ":*";
    if (permissions.includes(prefix)) {
      return true;
    }
  }
  return false;
};

2. 路由权限验证

系统自动将路由路径转换为权限码进行验证:

typescript 复制代码
const formatPathCode = (pathname: string) => {
  const code = pathname.replace(/\//g, ":").slice(1);
  // 创建页面
  if (code.endsWith(":create")) {
    return code;
  }
  // 编辑页面、详情页面
  if (code.endsWith(":edit") || code.endsWith(":detail")) {
    return code
      .split(":")
      .filter((s) => !/^\d+$/.test(s))
      .join(":");
  }
  // 列表页面
  return `${code}:list`;
};

权限组件体系

1. AuthGuard - 路由守卫

AuthGuard 组件负责路由级别的权限控制,在用户访问页面时进行权限验证:

typescript 复制代码
export const AuthGuard: React.FC<AuthGuardProps> = ({ children }) => {
  const location = useLocation();
  const { token, updateUserInfo, checkMenuPermissions } = useAuthStore();

  // 无 token 跳转登录页
  if (!token) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }

  // 检查页面权限
  const isPermission = checkMenuPermissions(location.pathname);
  return isPermission ? children : <Navigate to="/403" replace />;
};

2. AuthWrap - 组件级权限控制

AuthWrap 组件用于控制组件的显示/隐藏:

typescript 复制代码
export const AuthWrap: React.FC<AuthWrapProps> = ({
  code,
  children,
  hidden = false,
}) => {
  const isPermission = useAuthStore.getState().checkPermissions(code);
  if (isPermission && !hidden) {
    return children;
  }
  return null;
};

3. AuthConfirm - 操作级权限控制

AuthConfirm 组件用于需要确认的操作权限控制:

typescript 复制代码
export const AuthConfirm: React.FC<AuthConfirmProps> = (props) => {
  const handleConfirm = () => {
    modalApi.confirm({
      title: props.title,
      content: props.description,
      onOk: props.onConfirm,
      onCancel: props.onCancel,
    });
  };

  return (
    <AuthWrap code={props.code} hidden={props.hidden}>
      <span onClick={handleConfirm} className={props.className}>
        {props.children}
      </span>
    </AuthWrap>
  );
};

实际应用示例

1. 用户管理页面权限控制

typescript 复制代码
export default function UserPage() {
  return (
    <ProTable<User.Item>
      // ... 表格配置
      toolBarRender={() => [
        <AuthWrap code="system:user:create">
          <UserModalForm mode="create" onSuccess={handleSuccess}>
            <Button type="primary">Create User</Button>
          </UserModalForm>
        </AuthWrap>,
      ]}
      columns={[
        // ... 其他列
        {
          title: "Actions",
          render: (_, entity) => (
            <Space size="middle">
              <AuthWrap code="system:user:detail">
                <UserModalForm mode="detail" initialValues={entity}>
                  <a>Detail</a>
                </UserModalForm>
              </AuthWrap>
              <MoreButton>
                <AuthWrap code="system:user:edit">
                  <UserModalForm mode="edit" initialValues={entity}>
                    <a>Edit</a>
                  </UserModalForm>
                </AuthWrap>
                <AuthConfirm
                  code="system:user:delete"
                  title="Are you sure you want to delete this user?"
                  onConfirm={handleDelete}
                >
                  Delete User
                </AuthConfirm>
              </MoreButton>
            </Space>
          ),
        },
      ]}
    />
  );
}

2. 动态菜单生成

系统根据用户权限动态生成菜单:

typescript 复制代码
export const getMenuData = (): AppRouter[] => {
  const { checkMenuPermissions } = useAuthStore.getState();

  const getMenuList = (menuList: AppRouter[]): AppRouter[] => {
    return menuList
      .filter((item) => {
        if (!item.path) return false;
        if (item.children) return true;
        return checkMenuPermissions(item.path);
      })
      .map((item) => ({
        ...item,
        children: item.children ? getMenuList(item.children) : undefined,
      }))
      .filter((item) => {
        // 隐藏无子菜单的项目
        if (item.children?.length === 0) {
          return false;
        }
        return true;
      });
  };
  return getMenuList(pageRoutes);
};

权限系统特点

1. 细粒度控制

  • 路由级权限:控制页面访问
  • 组件级权限:控制功能模块显示
  • 操作级权限:控制具体操作按钮

2. 智能权限匹配

  • 支持精确权限码匹配
  • 支持通配符权限(*
  • 支持层级权限继承(system:user:*system:*

3. 用户体验优化

  • 无权限内容自动隐藏,避免界面混乱
  • 权限验证失败时优雅降级
  • 支持权限状态持久化

4. 权限码命名规范

  • 使用 module:resource:action 格式
  • 保持命名一致性
  • 避免过于复杂的权限层级

5. 组件使用建议

场景 组件 示例
页面访问控制 AuthGuard 路由级权限验证
功能模块显示 AuthWrap 按钮、表单等组件
危险操作确认 AuthConfirm 删除、导出等操作

🎯 总结:简单的权限控制方案

核心收益

通过这套权限系统,我实现了:

  • 开发效率提升:声明式权限控制,减少重复代码
  • 用户体验优化:无权限内容自动隐藏,界面更清爽
  • 维护成本降低:权限逻辑集中管理,变更更简单
  • 安全性增强:前后端权限双重验证

技术亮点

  1. 智能权限匹配:支持精确匹配、通配符匹配、层级继承
  2. 组件化设计:三个核心组件覆盖所有权限场景
  3. TypeScript 支持:完整的类型定义,开发体验优秀
  4. 性能优化:权限验证结果缓存,避免重复计算

适用场景

  • 中小型管理系统:权限结构相对简单
  • 快速开发项目:需要快速构建权限控制
  • 用户体验优先:注重界面美观和交互流畅
  • 前后端分离:基于 API 的权限数据交互

🧭 写在最后

这套权限系统是我在开发 rustzen-admin 过程中的真实实践,从最初的直接写死权限到最终的简单设计。在目前项目阶段,简单的权限控制已经足够满足需求。前后端统一的权限规范,可以避免权限数据不一致的问题,也方便后续的权限扩展。 如果你也在为权限控制而烦恼,不妨试试这套方案。也许它会像帮助我一样,让你的权限系统变得更加简单和易维护。


📫 相关资源

相关推荐
roamingcode1 小时前
Claude Code NPM 包发布命令
前端·npm·node.js·claude·自定义指令·claude code
码哥DFS1 小时前
NPM模块化总结
前端·javascript
灵感__idea2 小时前
JavaScript高级程序设计(第5版):代码整洁之道
前端·javascript·程序员
唐璜Taro2 小时前
electron进程间通信-IPC通信注册机制
前端·javascript·electron
陪我一起学编程3 小时前
创建Vue项目的不同方式及项目规范化配置
前端·javascript·vue.js·git·elementui·axios·企业规范
LinXunFeng4 小时前
Flutter - 详情页初始锚点与优化
前端·flutter·开源
GISer_Jing4 小时前
Vue Teleport 原理解析与React Portal、 Fragment 组件
前端·vue.js·react.js
Summer不秃4 小时前
uniapp 手写签名组件开发全攻略
前端·javascript·vue.js·微信小程序·小程序·html
coderklaus4 小时前
Base64编码详解
前端·javascript
NobodyDJ4 小时前
Vue3 响应式大对比:ref vs reactive,到底该怎么选?
前端·vue.js·面试