React 本身没有像 Vue (beforeEach) 那样内置的路由守卫 ,一般都是通过 React Router + 登录状态 + 权限控制 + 高阶组件(HOC) / 自定义组件 / Hook 来实现。
React 企业项目(后台管理、ERP、OA、CMS)一般都会实现四层权限:
登录认证(Auth)
↓
路由权限(Route Guard)
↓
菜单权限(Menu Permission)
↓
按钮权限(Button Permission)
下面按照企业项目的方式完整讲解。
一、React 路由守卫是什么?
作用:
用户访问页面之前,先判断有没有权限。
例如:
未登录
访问
/login
√
/home
×
跳到 login
/user
×
/system
×
登录以后
admin
/home
√
/system
√
/user
√
普通用户
/home
√
/system
×
/user
√
所以路由守卫主要干三件事:
① 是否登录
② 是否有角色权限
③ 是否有页面权限
二、React Router v6 路由
例如:
import { BrowserRouter, Routes, Route } from "react-router-dom";
<BrowserRouter>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/" element={<Layout />}>
<Route path="home" element={<Home />} />
<Route path="user" element={<User />} />
<Route path="system" element={<System />} />
</Route>
</Routes>
</BrowserRouter>
但是这里任何人都能访问。
需要加守卫。
三、第一层:登录守卫
创建
AuthRoute.tsx
import { Navigate } from "react-router-dom";
export default function AuthRoute({ children }) {
const token = localStorage.getItem("token");
if (!token) {
return <Navigate to="/login" replace />;
}
return children;
}
然后包裹页面。
<Route
path="/"
element={
<AuthRoute>
<Layout />
</AuthRoute>
}
/>
流程:
访问
↓
有没有token
↓
没有
↓
Navigate("/login")
↓
有
↓
继续访问
四、token 一般存哪里?
企业里一般:
登录
↓
接口返回
{
token:"xxxxx"
}
保存
localStorage.setItem("token", token);
退出登录
localStorage.removeItem("token");
或者
Redux
store.user.token
或者
Context
UserContext
五、第二层:角色权限
后台一般返回:
{
"username":"admin",
"role":"admin"
}
或者
{
"roles":[
"admin",
"editor"
]
}
定义路由:
const routes = [
{
path:"/home",
element:<Home/>
},
{
path:"/system",
roles:["admin"],
element:<System/>
},
{
path:"/user",
roles:["admin","editor"],
element:<User/>
}
]
守卫:
const role = "editor";
if(route.roles){
if(!route.roles.includes(role)){
return <Navigate to="/403"/>
}
}
效果:
admin
home
√
system
√
user
√
editor
home
√
system
×
user
√
六、第三层:菜单权限
后台返回:
[
"/home",
"/user"
]
说明:
用户只能看到
首页
用户管理
菜单配置:
const menus = [
{
path:"/home",
title:"首页"
},
{
path:"/user",
title:"用户"
},
{
path:"/system",
title:"系统设置"
}
]
过滤:
const permission = ["/home","/user"];
const menu = menus.filter(item=>{
return permission.includes(item.path);
})
最终:
首页
用户管理
系统设置不会显示。
七、第四层:按钮权限
后台返回:
[
"user:add",
"user:delete",
"user:update"
]
页面:
<button>新增</button>
<button>删除</button>
<button>修改</button>
可以封装:
function Permission({ code, children }) {
const buttons = [
"user:add",
"user:update"
];
if(buttons.includes(code)){
return children;
}
return null;
}
使用:
<Permission code="user:add">
<Button>新增</Button>
</Permission>
<Permission code="user:delete">
<Button>删除</Button>
</Permission>
结果:
新增 √
删除 ×
八、动态路由权限(企业最常见)
很多后台不会把所有路由写死。
登录后:
login
↓
token
↓
获取用户信息
↓
获取权限
↓
后台返回路由
↓
动态生成React Router
例如后台返回:
[
{
"path":"/home",
"component":"Home"
},
{
"path":"/user",
"component":"User"
}
]
前端映射:
const componentMap = {
Home: Home,
User: User,
System: System
};
const routes = backendRoutes.map(item => ({
path: item.path,
element: React.createElement(componentMap[item.component])
}));
这样后台控制:
哪些页面能访问
不用重新发版。
九、完整流程(企业项目)
用户访问
↓
Route Guard
↓
有没有token?
↓
没有
↓
login
↓
登录
↓
token
↓
获取用户信息
↓
获取角色
↓
获取菜单权限
↓
获取按钮权限
↓
动态生成菜单
↓
动态生成路由
↓
进入首页
十、推荐项目目录结构
src
│
├── router
│ ├── index.tsx // 路由入口
│ ├── routes.ts // 路由配置
│ ├── AuthRoute.tsx // 登录守卫
│ ├── PermissionRoute.tsx// 权限守卫
│
├── layouts
│ └── Layout.tsx
│
├── pages
│ ├── Login
│ ├── Home
│ ├── User
│ └── System
│
├── store
│ └── user.ts // token、角色、权限
│
├── hooks
│ └── usePermission.ts // 权限 Hook
│
├── components
│ └── Permission.tsx // 按钮权限组件
│
└── utils
└── auth.ts // token 工具
十一、企业级最佳实践(React Router v6 + Redux)
对于使用 React Router v6 + Redux(或 Zustand) 的中大型项目,推荐采用以下职责划分:
| 模块 | 职责 | 数据来源 |
|---|---|---|
| 登录认证 | 校验 Token 是否存在、是否过期 | localStorage + Redux |
| 路由守卫 | 拦截未登录用户、校验页面访问权限 | Redux 中的用户信息和权限 |
| 菜单权限 | 根据后端返回的菜单列表动态渲染侧边栏 | 后端菜单接口 |
| 动态路由 | 根据后端返回的路由配置生成可访问路由 | 路由配置接口 |
| 按钮权限 | 控制按钮、操作入口是否显示或禁用 | 后端权限码(如 user:add) |
| 权限 Hook | 封装权限判断逻辑(如 usePermission) |
Redux/Zustand |
Permission 组件 |
在 JSX 中优雅地控制权限显示 | 权限 Hook |
这种分层方式具有以下优点:
-
职责清晰:认证、路由、菜单、按钮权限互不耦合。
-
便于扩展:新增角色或权限类型时,只需调整权限配置和判断逻辑。
-
符合企业后台实践:适用于 React + Ant Design、React + Material UI 等常见后台管理系统,也便于与 RBAC(基于角色的访问控制)模型结合。
-
支持动态权限:能够结合后端返回的数据,实现菜单、路由和按钮权限的统一管理。
如果你正在准备前端面试,这套实现(登录认证 + 路由守卫 + 动态路由 + 菜单权限 + 按钮权限 + RBAC)基本覆盖了 React 中后台项目关于权限控制的高频考点。