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

React路由角色权限控制实现方案咨询(附现有路由代码)

React 基于角色的路由权限控制实现方案

当然可以用 Context 来做角色校验,这是 React 中实现路由权限控制的常用方案之一,下面是一套完整的最优实现流程:

一、创建 AuthContext 管理用户角色状态

先通过全局上下文统一管理用户的登录状态和角色信息,让所有组件都能便捷获取/修改这些数据:

// src/contexts/AuthContext.js
import { createContext, useContext, useState, useEffect } from 'react';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
  // 从localStorage读取初始化角色,实现页面刷新后状态保留
  const [userRole, setUserRole] = useState(localStorage.getItem('userRole') || null);

  // 登录方法:同步保存角色到状态和本地存储
  const login = (role) => {
    setUserRole(role);
    localStorage.setItem('userRole', role);
  };

  // 退出登录:清除角色状态和本地存储
  const logout = () => {
    setUserRole(null);
    localStorage.removeItem('userRole');
  };

  return (
    <AuthContext.Provider value={{ userRole, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

// 自定义Hook,简化上下文获取
export const useAuth = () => useContext(AuthContext);

然后在项目根组件(比如 main.jsx)中用 AuthProvider 包裹整个应用:

// src/main.jsx
import { AuthProvider } from './contexts/AuthContext';
import { BrowserRouter } from 'react-router-dom';
import RoutesComponent from './Routes';

ReactDOM.createRoot(document.getElementById('root')).render(
  <AuthProvider>
    <BrowserRouter>
      <RoutesComponent />
    </BrowserRouter>
  </AuthProvider>
);

二、实现路由守卫组件 PrivateRoute

这个组件是权限校验的核心,负责判断当前用户是否有权限访问目标路由:

// src/components/PrivateRoute.js
import { Navigate } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';

const PrivateRoute = ({ allowedRoles, element }) => {
  const { userRole } = useAuth();

  // 未登录直接跳转到首页登录
  if (!userRole) {
    return <Navigate to="/" replace />;
  }

  // 角色不在允许列表中,跳转到首页
  if (!allowedRoles.includes(userRole)) {
    return <Navigate to="/" replace />;
  }

  // 权限校验通过,渲染目标组件
  return element;
};

export default PrivateRoute;

三、修改你的 useRoutes 配置

把需要保护的路由用 PrivateRoute 包裹,指定对应的允许角色:

// src/Routes.js
import { useRoutes } from 'react-router-dom';
import PrivateRoute from './components/PrivateRoute';
// 导入你的页面组件
import Firstpage from './pages/Firstpage';
import Studenpage from './pages/Studenpage';
import Main from './pages/Main';
import Pfeextern from './pages/Pfeextern';
import Uploadfile from './pages/Uploadfile';
import Propose from './pages/Propose';
import HomePageEncadreur from './pages/HomePageEncadreur';
import Mainn from './pages/Mainn';
import Request from './pages/Request';
import LoginAdmin from './pages/LoginAdmin';
import Adminnn from './pages/Adminnn';
import Students from './pages/Students';
import Teacher from './pages/Teacher';
import Jury from './pages/Jury';
import Form from './pages/Form';
import Feedback from './pages/Feedback';
import Calendar from './pages/Calendar';

const RoutesComponent = () => {
  const routes = useRoutes([
    {
      path: "/",
      element: <Firstpage />,
    },
    // 学生路由:仅允许student角色访问
    {
      path: "/Student",
      element: <PrivateRoute allowedRoles={['student']} element={<Studenpage />} />,
      children: [
        { path: "", element: <Main /> },
        { path: "form", element: <Pfeextern /> },
        { path: "upload", element: <Uploadfile /> },
        { path: "propose", element: <Propose /> }
      ],                     
    },
    // 教师路由:仅允许teacher角色访问
    {
      path: "/teacher",
      element: <PrivateRoute allowedRoles={['teacher']} element={<HomePageEncadreur />} />,
      children: [
        { path: "", element: <Mainn /> },
        { path: "Request", element: <Request /> },
      ],
    },
    // 管理员登录页:公开访问
    {
      path: "/loginAdmin",
      element: <LoginAdmin />,
    },
    // 管理员路由:仅允许admin角色访问
    {
      path: '/Admin',
      element: <PrivateRoute allowedRoles={['admin']} element={<Adminnn />} />,
      children: [
        { path: "", element: <Students /> },
        { path: "team", element: <Teacher /> },
        { path: "jury", element: <Jury /> },
        { path: "form", element: <Form /> },
        { path: "feedback", element: <Feedback /> },
        { path: "calendar", element: <Calendar /> },
      ],
    },
  ]);

  return <>{routes}</>;
};

export default RoutesComponent;

四、处理首页登录的角色选择逻辑

在 Firstpage 组件中添加角色选择(建议用单选按钮,因为用户只能选一个角色),并调用 AuthContext 的登录方法:

// src/pages/Firstpage.js
import { useState } from 'react';
import { useAuth } from '../contexts/AuthContext';
import { useNavigate } from 'react-router-dom';

const Firstpage = () => {
  const { login } = useAuth();
  const navigate = useNavigate();
  const [selectedRole, setSelectedRole] = useState(null);

  const handleLogin = () => {
    if (!selectedRole) {
      alert('请选择一个角色');
      return;
    }
    // 保存角色并跳转到对应路由
    login(selectedRole);
    switch(selectedRole) {
      case 'student':
        navigate('/Student');
        break;
      case 'teacher':
        navigate('/teacher');
        break;
      case 'admin':
        navigate('/Admin');
        break;
      default:
        navigate('/');
    }
  };

  return (
    <div>
      <h1>登录页面</h1>
      <div>
        <label>
          <input
            type="radio"
            name="role"
            value="student"
            onChange={(e) => setSelectedRole(e.target.value)}
          />
          学生
        </label>
        <label>
          <input
            type="radio"
            name="role"
            value="teacher"
            onChange={(e) => setSelectedRole(e.target.value)}
          />
          教师
        </label>
        <label>
          <input
            type="radio"
            name="role"
            value="admin"
            onChange={(e) => setSelectedRole(e.target.value)}
          />
          管理员
        </label>
      </div>
      <button onClick={handleLogin}>登录</button>
    </div>
  );
};

export default Firstpage;

五、补充说明

  • 角色值要统一:路由配置和登录逻辑中的角色字符串要完全一致(比如都是小写的student),避免拼写/大小写错误导致校验失败。
  • 持久化优化:如果需要更高的安全性,可以把角色存储在后端返回的 HttpOnly Cookie 中,前端通过接口校验权限。
  • 退出功能:在各角色页面中可以添加退出按钮,调用 useAuth 中的 logout 方法后跳转到首页。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 12:24:52