news 2026/6/9 21:38:33

React Router 7 全局路由保护

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
React Router 7 全局路由保护

之前项目的路由保护是这样的:每个需要登录的页面都判断一下token,没有就跳转登录页。

// 之前:每个页面都要写 const SomePage = () => { const token = localStorage.getItem('token'); if (!token) { return <Navigate to="/login" />; } return <div>页面内容</div>; };

这样写有几个问题:

  1. 每个页面都要重复这个逻辑
  2. 万一漏了一个页面,就有安全漏洞
  3. 代码很乱,业务逻辑混在一起

后来我改成全局路由保护,清爽多了。

React Router 7 的新特性

React Router 7 推出了<BrowserRouter>basename和一些新特性,但最实用的是嵌套路由。

但我的方案不是在每个路由外面套<ProtectedRoute>,而是在main.jsx里套一个全局的:

// main.jsx <BrowserRouter> <ProtectedRoute> {/* 全局保护,只套一次 */} <ConfigProvider> <App /> </ConfigProvider> </ProtectedRoute> </BrowserRouter>

这样<App />里面的所有路由都会经过保护逻辑。

ProtectedRoute 的实现

ProtectedRoute组件要做三件事:

  1. 检查 token,没有就跳登录
  2. 检查路由是否合法(防止访问不存在的页面)
  3. 处理登录后跳回原页面的逻辑
const ProtectedRoute = ({ children }) => { const location = useLocation(); const pathname = location.pathname; // 1. 检查路由是否合法 const allowedRoutes = [ "/login", "/", "/chat", "/customer", "/review-dashboard", "/pdf-annotator/:id", ... ]; const isValidRoute = allowedRoutes.some(route => pathname === route || pathname.startsWith(`${route}/`) ); if (!isValidRoute) { return <Navigate to="/404" replace />; } // 2. 登录页面直接放行 if (pathname === "/login") { return <>{children}</>; } // 3. 检查 token const token = localStorage.getItem("token"); if (!token) { localStorage.setItem("pathname", pathname); // 保存原路径 return <Navigate to="/login" replace />; } // 4. 根路径重定向 if (pathname === "/") { return <Navigate to="/chat" replace />; } return <>{children}</>; };

这样写的好处:

  • 所有路由都在一个地方管理,不会漏
  • 未定义的路由自动跳 404
  • 登录后自动跳回原页面
但是有个坑:401 错误处理

用户登录后,token 会过期。这时候后端返回 401,我需要自动跳转到登录页。

但这个逻辑不能写在ProtectedRoute里,因为它只在路由切换时执行,不会响应 API 请求。

我把它写在了 Axios 拦截器里:

// request.js export let isRelogin = { show: false }; request.interceptors.response.use( (response) => { if (response.data.code === 401) { if (!isRelogin.show) { isRelogin.show = true; message.error('登录状态已过期'); localStorage.setItem("pathname", window.location.pathname); localStorage.removeItem("token"); window.location.href = "/login"; } } else if (response.data.code !== 200) { message.error(response.data.msg); return Promise.reject(response.data); } return response; }, (error) => { if (error.response?.status === 401) { localStorage.removeItem("token"); window.location.href = "/login"; } return Promise.reject(error); } );

这里有个坑:如果多个请求同时返回 401,会弹出多次错误提示。

我用了个isRelogin.show标志位,确保只弹一次:

export let isRelogin = { show: false }; if (response.data.code === 401) { if (!isRelogin.show) { // 只处理第一次 isRelogin.show = true; message.error('登录状态已过期'); window.location.href = "/login"; } }

登录成功后,记得重置这个标志位:

// 登录成功后 isRelogin.show = false;
懒加载怎么处理?

React Router 7 推荐用懒加载,但ProtectedRoute会阻止懒加载的组件渲染。

我的方案是:只懒加载页面组件,不懒加载ProtectedRoute

// App.jsx const HomePage = lazy(() => import("./view/HomePage")); const PDFAnnotatorDemo = lazy(() => import("./view/PDFAnnotatorDemo")); const App = () => { return ( <Suspense fallback={<PageLoading />}> <Routes> <Route path="/homepage" element={<HomePage />} /> <Route path="/pdf-annotator/:id" element={<PDFAnnotatorDemo />} /> ... </Routes> </Suspense> ); };

ProtectedRoutemain.jsx里,不会被懒加载,所以一开始就会加载。

最后的效果

现在的路由架构:

  • main.jsx:全局保护 + 登录页不懒加载
  • App.jsx:懒加载所有其他页面
  • request.js:401 自动跳登录

代码清爽多了,也不用担心漏保护某个页面。

几个踩坑总结
  1. 全局保护比单独保护好:一次套在main.jsx里就行
  2. 401 处理要防重复:用isRelogin.show标志位
  3. 路由白名单要维护:未定义的路由跳 404
  4. 懒加载不能保护 ProtectedRoute:它要最先加载
  5. 登录后要跳回原路径:用localStorage.pathname保存
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/7 17:49:20

Pi0机器人控制中心生产就绪:健康检查+自动重启+日志滚动策略

Pi0机器人控制中心生产就绪&#xff1a;健康检查自动重启日志滚动策略 1. 项目概述 Pi0机器人控制中心是基于π₀(Pi0)视觉-语言-动作(VLA)模型构建的通用机器人操控界面。这个专业级的Web交互终端通过多视角相机输入和自然语言指令&#xff0c;能够预测机器人的6自由度(6-DO…

作者头像 李华
网站建设 2026/6/8 2:31:48

Vue 3中的Prismic数据过滤与排序

在现代Web开发中,数据的动态获取和处理是每个前端开发者都必须面对的问题。Prismic作为一个强大的内容管理系统(CMS),提供了丰富的API来帮助我们管理和获取数据。在本文中,我们将探讨如何在Vue 3中使用Composition API结合Prismic的查询功能来过滤和排序数据。 背景知识 …

作者头像 李华
网站建设 2026/5/28 14:16:05

RTX 4090显卡优化方案:造相-Z-Image文生图引擎防爆显存全攻略

RTX 4090显卡优化方案&#xff1a;造相-Z-Image文生图引擎防爆显存全攻略 你是不是也经历过这样的崩溃时刻&#xff1f; 刚输入一句“晨光中的写实人像&#xff0c;柔焦皮肤&#xff0c;8K细节”&#xff0c;点击生成—— 进度条才走到30%&#xff0c;显存使用率就飙到99%&…

作者头像 李华
网站建设 2026/6/6 11:30:19

Git-RSCLIP快速部署:一键搭建遥感AI分析平台

Git-RSCLIP快速部署&#xff1a;一键搭建遥感AI分析平台 遥感图像分析长期面临一个现实困境&#xff1a;专业模型部署门槛高、数据标注成本大、场景泛化能力弱。你是否也经历过——花两周配置环境&#xff0c;却卡在CUDA版本兼容问题上&#xff1b;下载了开源模型&#xff0c;…

作者头像 李华
网站建设 2026/6/3 3:05:22

UEFI启动界面定制终极指南:告别千篇一律,打造专属开机体验

UEFI启动界面定制终极指南&#xff1a;告别千篇一律&#xff0c;打造专属开机体验 【免费下载链接】HackBGRT Windows boot logo changer for UEFI systems 项目地址: https://gitcode.com/gh_mirrors/ha/HackBGRT 你是否厌倦了每次开机都看到那毫无个性的厂商Logo&…

作者头像 李华
网站建设 2026/6/8 23:46:53

基于数据库的制造过程查询智能客服:架构设计与性能优化实战

基于数据库的制造过程查询智能客服&#xff1a;架构设计与性能优化实战 一、制造业查询场景的“老毛病” 数据孤岛&#xff1a;ERP、MES、APS、WMS 各自为政&#xff0c;一条产线查询往往要跨四五个系统&#xff0c;人工客服得开四五个窗口。查询口径不统一&#xff1a;同一工…

作者头像 李华