
本文介绍如何结合 useAuth 自定义 Hook 与 React Router v6 的嵌套路由机制,安全、可维护地实现角色权限校验——仅允许指定角色(如 Admin、Engineer)访问特定路由页面。
本文介绍如何结合 `useauth` 自定义 hook 与 react router v6 的嵌套路由机制,安全、可维护地实现角色权限校验——仅允许指定角色(如 admin、engineer)访问特定路由页面。
在现代 React 应用中,基于角色的路由控制(Role-Based Routing)是保障前端权限安全的关键一环。它不应仅依赖 UI 层隐藏菜单,而需在路由跳转前进行实时权限校验,防止用户通过手动修改 URL 绕过限制。
核心思路是:将权限校验逻辑从组件内部抽离至路由层,利用 element 属性包裹受保护的路由组件,并注入角色校验逻辑。以下是完整实现方案:
✅ 1. 定义统一的权限守卫组件(ProtectedRoute)
创建 src/components/ProtectedRoute.jsx,封装角色校验与重定向逻辑:
import { Navigate } from 'react-router-dom';
import useAuth from '../hooks/useAuth';
const ProtectedRoute = ({ children, allowedRoles = [] }) => {
const { status } = useAuth(); // 假设 status 返回 'admin' | 'engineer' | 'operations'
// 精确匹配(大小写敏感),也可改为 includes 或 toLowerCase() 统一处理
const hasPermission = allowedRoles.some(role => role.toLowerCase() === status.toLowerCase());
if (!hasPermission) {
return <Navigate to="/auth/unauthorized" replace />;
}
return children;
};
export default ProtectedRoute;⚠️ 注意:status 来自 useAuth,其值应与 allowedRoles 中声明的角色语义一致(如 "Admin" → "admin")。建议后端返回标准化小写角色名,或在 useAuth 中统一归一化。
✅ 2. 改造路由配置,注入 allowedRoles
更新 routes.jsx,为每条路由显式声明所需角色:
import Overview from "./views/Overview";
import Teams from "./views/Teams";
import Apps from "./views/Apps";
import ProtectedRoute from "../components/ProtectedRoute";
const dashRoutes = [
{
path: "/overview",
element: (
<ProtectedRoute allowedRoles={["admin"]}>
<Overview />
</ProtectedRoute>
),
layout: "/dashboard",
},
{
path: "/teams",
element: (
<ProtectedRoute allowedRoles={["admin"]}>
<Teams />
</ProtectedRoute>
),
layout: "/dashboard",
},
{
path: "/apps",
element: (
<ProtectedRoute allowedRoles={["admin", "engineer"]}>
<Apps />
</ProtectedRoute>
),
layout: "/dashboard",
},
];
export default dashRoutes;✅ 3. 更新 Dashboard 组件,使用动态路由渲染
移除硬编码的
import { Navigate, Route, Routes } from "react-router-dom";
import routes from "#routes";
import useAuth from "../hooks/useAuth";
import { ChakraProvider } from "@chakra-ui/react";
import theme from "../theme";
export default function Dashboard() {
const { status } = useAuth();
const getRoutes = (routeList) => {
return routeList
.filter((prop) => prop.layout === "/dashboard")
.map((prop, key) => (
<Route
key={key}
path={prop.path}
element={prop.element} // ✅ 已含 ProtectedRoute 包裹
/>
));
};
return (
<ChakraProvider theme={theme} resetCss={false}>
<Routes>
{getRoutes(routes)}
{/* 默认重定向 */}
<Route
path="/dashboard"
element={<Navigate to="/dashboard/overview" replace />}
/>
{/* 404 捕获 */}
<Route path="*" element={<Navigate to="/auth/notfound" replace />} />
</Routes>
</ChakraProvider>
);
}✅ 4. 补充:服务端兜底与用户体验优化
- ? 永远不要仅依赖前端校验:ProtectedRoute 是用户体验增强手段,真实权限必须由后端 API 验证并返回 403。
- ? 支持异步加载:若 useAuth 依赖异步状态(如初始 loading),可在 ProtectedRoute 中添加 if (status === null) return
;。 - ? 扩展性设计:后续可将 allowedRoles 升级为 permissions: ['view:dashboard', 'edit:teams'],对接更细粒度的 RBAC 模型。
通过以上四步,你已构建出清晰、可复用、符合 React Router v6 最佳实践的角色路由体系——既保障安全性,又兼顾代码可读性与未来扩展性。



















