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

React Router未配置受保护路由 未登录可访问内部页求助

问题根因
  • 仅根路径/配置了登录态判断,/dashboard、/history等所有内部页面路由完全没加访问拦截,路由匹配到就直接渲染组件,直接输地址当然能进。
  • 登录状态只存在组件内存state里,页面一刷新state就重置回初始空对象,就算加了路由拦截,刷新后也会异常跳回登录页。
  • 现有代码里/employee路径重复绑定了两个组件,后写的Addemploye会覆盖前面的Employee组件路由,属于附带bug,需要一起修复。
修复方案

第一步:封装通用权限路由组件

新建ProtectedRoute.jsx,统一处理拦截逻辑,不用每个路由重复写判断:

import { Navigate } from "react-router-dom";

function ProtectedRoute({ children }) {
  // 优先从本地存储取登录态,避免刷新丢失
  const user = JSON.parse(localStorage.getItem("loginUser") || '{}');
  // 未登录直接跳登录页
  if (!user._id) {
    return <Navigate to="/login" replace />;
  }
  // 已登录正常渲染目标页面
  return children;
}

export default ProtectedRoute;

第二步:修改登录逻辑,持久化登录态

修改Login.jsx的登录成功回调,把用户信息存入localStorage,保证刷新不丢状态:

const login = () => {
  axios.post("/login", user).then((res) => {
    alert(res.data.message);
    const loginUser = res.data.user;
    setusers(loginUser);
    // 持久化存储登录态
    localStorage.setItem("loginUser", JSON.stringify(loginUser));
    history.push("/dashboard")
  });
};

后续补退出登录逻辑时,记得调用localStorage.removeItem("loginUser")清除存储,再跳回登录页即可。

第三步:改造App.js路由配置

所有需要权限的页面用ProtectedRoute包裹,同时修复重复路由问题:

import "./App.css";
import { Routes, Route, Navigate } from "react-router-dom";
import Dashboard from "./Components/After Login/Dashboard/Dashboard";
import Task from "./Components/After Login/Task/Task";
import Employee from "./Components/After Login/Employee/Employee";
import History from "./Components/After Login/History/History";
import Notification from "./Components/After Login/Notification/Notification";
import Popup from "./Components/After Login/Task/Popup";
import Addemploye from "./Components/After Login/Employee/Addemploye";
import EmployeeCard from "./Components/After Login/Employee/EmployeeCard";
import Login from "./Components/Before Login/Login/Login";
import ProtectedRoute from "./ProtectedRoute";
import { useState, useEffect } from "react";

function App() {
  const [user, setusers] = useState({});

  // 初始化时从本地存储同步登录态到state
  useEffect(() => {
    const savedUser = JSON.parse(localStorage.getItem("loginUser") || '{}');
    if (savedUser._id) setusers(savedUser);
  }, []);

  return (
    <Routes>
      {/* 根路径重定向逻辑 */}
      <Route
        path="/"
        element={
          user?._id ? <Navigate to="/dashboard" replace /> : <Navigate to="/login" replace />
        }
      />
      {/* 登录页,已登录访问直接跳控制台 */}
      <Route path="/login" element={
        user?._id ? <Navigate to="/dashboard" replace /> : <Login setusers={setusers} />
      } />
      
      {/* 以下为受保护路由,全部接入权限校验 */}
      <Route path="/dashboard" element={<ProtectedRoute><Dashboard /></ProtectedRoute>} />
      <Route path="/task" element={<ProtectedRoute><Task /></ProtectedRoute>} />
      <Route path="/createtask" element={<ProtectedRoute><Popup /></ProtectedRoute>} />
      <Route path="/employee" element={<ProtectedRoute><Employee /></ProtectedRoute>} />
      {/* 给新增员工页分配独立路径,解决路由重复覆盖问题 */}
      <Route path="/employee/add" element={<ProtectedRoute><Addemploye /></ProtectedRoute>} />
      <Route path="/history" element={<ProtectedRoute><History /></ProtectedRoute>} />
      <Route path="/notification" element={<ProtectedRoute><Notification /></ProtectedRoute>} />
      <Route path="/employee/:id" element={<ProtectedRoute><EmployeeCard /></ProtectedRoute>} />
    </Routes>
  );
}

export default App;
补充说明
  • 路由上的replace属性用于替换路由栈历史,避免用户点浏览器返回键出现异常跳回登录页的问题。
  • 如果后续要加角色权限控制(比如普通员工不能访问员工管理页),直接在ProtectedRoute组件里加角色判断逻辑即可,不需要修改每个页面的代码。
  • 本地存储存用户信息仅为前端简易方案,生产环境建议结合token做鉴权,接口请求统一携带token,后端校验有效期,前端拿到401状态码自动清除登录态跳回登录页。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 11:39:42