You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Ant Design多角色侧边栏及Dashboard权限配置技术问询

多角色Ant Design Dashboard权限控制实现方案

直接给出最优解:条件渲染 + 路由守卫(权限拦截) 的组合方案,既能满足UI层面的菜单和页面展示控制,又能从路由层面拦截无权限访问,同时配合后端接口校验确保安全性。

一、侧边栏菜单的角色控制

实现思路

  1. 维护一份角色-菜单映射配置,统一管理不同角色可访问的菜单路径、名称、图标等信息;
  2. 前端获取当前登录用户的角色后,过滤出对应菜单列表,渲染Ant Design的Menu组件;
  3. 配合路由守卫,防止用户直接输入URL跳转无权限路由。

代码示例

1. 角色菜单配置表

// src/config/menu.js
import { DashboardOutlined, UserOutlined, BookOutlined, ScoreOutlined, ReadOutlined } from '@ant-design/icons';

export const roleMenuMap = {
  admin: [
    { key: 'dashboard', label: '控制台', path: '/dashboard', icon: <DashboardOutlined /> },
    { key: 'user-manage', label: '用户管理', path: '/users', icon: <UserOutlined /> },
    { key: 'course-manage', label: '课程管理', path: '/courses', icon: <BookOutlined /> },
  ],
  teacher: [
    { key: 'dashboard', label: '控制台', path: '/dashboard', icon: <DashboardOutlined /> },
    { key: 'my-courses', label: '我的课程', path: '/my-courses', icon: <BookOutlined /> },
    { key: 'grade-manage', label: '成绩管理', path: '/grades', icon: <ScoreOutlined /> },
  ],
  student: [
    { key: 'dashboard', label: '控制台', path: '/dashboard', icon: <DashboardOutlined /> },
    { key: 'my-learning', label: '我的学习', path: '/my-learning', icon: <ReadOutlined /> },
    { key: 'my-scores', label: '我的成绩', path: '/my-scores', icon: <ScoreOutlined /> },
  ],
};

2. 侧边栏组件渲染

// src/components/Sidebar.js
import { Menu } from 'antd';
import { useNavigate, useLocation } from 'react-router-dom';
import { useSelector } from 'react-redux'; // 也可使用React Context存储用户状态
import { roleMenuMap } from '@/config/menu';

const Sidebar = () => {
  const navigate = useNavigate();
  const { pathname } = useLocation();
  const { role } = useSelector(state => state.user);
  
  // 根据角色过滤可访问菜单
  const currentMenus = roleMenuMap[role] || [];
  // 匹配当前路由对应的菜单key
  const selectedKey = currentMenus.find(item => item.path === pathname)?.key || 'dashboard';

  return (
    <Menu
      mode="inline"
      selectedKeys={[selectedKey]}
      style={{ height: '100%', borderRight: 0 }}
    >
      {currentMenus.map(menu => (
        <Menu.Item
          key={menu.key}
          icon={menu.icon}
          onClick={() => navigate(menu.path)}
        >
          {menu.label}
        </Menu.Item>
      ))}
    </Menu>
  );
};

export default Sidebar;

二、同路由/dashboard的多角色页面展示

实现思路

在/dashboard对应的组件中,根据当前用户角色条件渲染不同的子组件,逻辑集中且易维护。

代码示例

1. 多角色Dashboard子组件

// src/pages/Dashboard/AdminDashboard.js
const AdminDashboard = () => {
  return (
    <div>
      <h2>管理员控制台</h2>
      {/* 管理员专属统计面板、用户操作模块 */}
    </div>
  );
};

// src/pages/Dashboard/TeacherDashboard.js
const TeacherDashboard = () => {
  return (
    <div>
      <h2>导师控制台</h2>
      {/* 导师专属课程管理、成绩统计模块 */}
    </div>
  );
};

// src/pages/Dashboard/StudentDashboard.js
const StudentDashboard = () => {
  return (
    <div>
      <h2>学生控制台</h2>
      {/* 学生专属学习进度、成绩查询模块 */}
    </div>
  );
};

2. 主Dashboard组件的条件渲染

// src/pages/Dashboard/index.js
import { useSelector } from 'react-redux';
import AdminDashboard from './AdminDashboard';
import TeacherDashboard from './TeacherDashboard';
import StudentDashboard from './StudentDashboard';
import NoPermission from '@/pages/NoPermission';

const Dashboard = () => {
  const { role } = useSelector(state => state.user);

  switch (role) {
    case 'admin':
      return <AdminDashboard />;
    case 'teacher':
      return <TeacherDashboard />;
    case 'student':
      return <StudentDashboard />;
    default:
      return <NoPermission />;
  }
};

export default Dashboard;

三、路由守卫的权限拦截

仅靠前端条件渲染不够安全,必须添加路由守卫拦截无权限访问:

// src/components/ProtectedRoute.js
import { Navigate, Outlet } from 'react-router-dom';
import { useSelector } from 'react-redux';

const ProtectedRoute = ({ allowedRoles }) => {
  const { role, isLoggedIn } = useSelector(state => state.user);

  // 未登录跳转登录页
  if (!isLoggedIn) {
    return <Navigate to="/login" replace />;
  }

  // 角色不在允许列表内跳转403页面
  if (!allowedRoles.includes(role)) {
    return <Navigate to="/403" replace />;
  }

  // 权限通过,渲染子路由内容
  return <Outlet />;
};

export default ProtectedRoute;

全局路由配置

// src/routes/index.js
import { Routes, Route, Navigate } from 'react-router-dom';
import ProtectedRoute from '@/components/ProtectedRoute';
import Login from '@/pages/Login';
import Dashboard from '@/pages/Dashboard';
import UserManage from '@/pages/UserManage';
import MyCourses from '@/pages/MyCourses';
import NoPermission from '@/pages/NoPermission';

const AppRoutes = () => {
  return (
    <Routes>
      <Route path="/login" element={<Login />} />
      {/* 所有需要登录的路由嵌套在此 */}
      <Route element={<ProtectedRoute allowedRoles={['admin', 'teacher', 'student']} />}>
        <Route path="/dashboard" element={<Dashboard />} />
        {/* 仅管理员可访问的路由 */}
        <Route element={<ProtectedRoute allowedRoles={['admin']} />}>
          <Route path="/users" element={<UserManage />} />
          <Route path="/courses" element={<CourseManage />} />
        </Route>
        {/* 仅导师可访问的路由 */}
        <Route element={<ProtectedRoute allowedRoles={['teacher']} />}>
          <Route path="/my-courses" element={<MyCourses />} />
          <Route path="/grades" element={<GradeManage />} />
        </Route>
        {/* 仅学生可访问的路由 */}
        <Route element={<ProtectedRoute allowedRoles={['student']} />}>
          <Route path="/my-learning" element={<MyLearning />} />
          <Route path="/my-scores" element={<MyScores />} />
        </Route>
      </Route>
      <Route path="/403" element={<NoPermission />} />
      <Route path="*" element={<Navigate to="/dashboard" replace />} />
    </Routes>
  );
};

export default AppRoutes;

关键注意事项

  1. 后端权限校验不可少:前端权限控制仅为UI优化,所有接口请求必须在后端做角色校验,防止用户通过调试工具篡改状态访问敏感数据;
  2. 角色存储安全:用户角色信息建议通过后端接口返回,存储在Redux/Context中,避免直接存在localStorage(易被篡改),后端可通过HttpOnly Cookie维护登录态;
  3. 可扩展性优化:菜单配置可改为后端接口返回,后续新增角色或调整菜单无需修改前端代码。

内容的提问来源于stack exchange,提问作者opu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 14:09:52