0Pricing
React Academy · 课时

受保护路由与身份验证守卫

使用包装组件或基于加载器的守卫,将未验证身份的用户重定向到登录页。

受保护路由与身份验证守卫 是 CoddyKit 上的免费 React Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。

为什么要保护路由

某些页面(仪表板、个人资料、管理页面)应该只能由通过身份验证的用户访问。React Router 提供两种方式:包装组件和基于加载器的保护机制。

身份验证状态结构

首先,请建立一个身份验证上下文,让组件可以读取它来判断用户是否已登录。

const AuthContext = React.createContext(null);

function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  const login = async (creds) => { const u = await apiLogin(creds); setUser(u); };
  const logout = () => setUser(null);
  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

export const useAuth = () => useContext(AuthContext);

包装组件保护机制

创建一个 PrivateRoute 组件来检查身份验证状态;如果用户未通过身份验证,则将其重定向到登录页。

import { Navigate, Outlet } from 'react-router-dom';

function PrivateRoute() {
  const { user } = useAuth();
  if (!user) return <Navigate to="/login" replace />;
  return <Outlet />;
}

// Usage in router:
{ element: <PrivateRoute />, children: [
  { path: '/dashboard', element: <Dashboard /> },
]}

保留重定向 URL

保存用户尝试访问的 URL,以便登录后将用户送回原页面。通过 Navigate 组件上的 state 传递该 URL。

function PrivateRoute() {
  const { user } = useAuth();
  const location = useLocation();
  if (!user) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }
  return <Outlet />;
}

// In login handler:
const location = useLocation();
const from = location.state?.from?.pathname || '/';
navigate(from, { replace: true });

基于加载器的保护机制(数据路由)

在数据路由接口中,向路由的 loader 添加身份验证检查。如果用户未通过身份验证,则抛出重定向。

import { redirect } from 'react-router-dom';

function requireAuth() {
  const token = localStorage.getItem('token');
  if (!token) throw redirect('/login');
  return token;
}

const router = createBrowserRouter([
  {
    path: '/dashboard',
    loader: requireAuth,
    element: <Dashboard />,
  },
]);

基于角色的保护机制

扩展保护机制以检查用户角色。如果用户缺少所需角色,则将其重定向到未授权页面。

function AdminRoute() {
  const { user } = useAuth();
  if (!user) return <Navigate to="/login" replace />;
  if (user.role !== 'admin') return <Navigate to="/unauthorized" replace />;
  return <Outlet />;
}

身份验证检查期间的加载状态

如果身份验证状态是异步加载的(例如从服务器加载),请在检查处于等待状态时显示加载指示器,以避免登录页短暂闪现。

function PrivateRoute() {
  const { user, isLoading } = useAuth();
  if (isLoading) return <Spinner />;
  if (!user) return <Navigate to="/login" replace />;
  return <Outlet />;
}

同时保护多个路由

将所有受保护的路由归入一个 PrivateRoute 包装器下,这样就不必在每个路由上单独重复保护机制。

const router = createBrowserRouter([
  { path: '/login', element: <Login /> },
  {
    element: <PrivateRoute />,
    children: [
      { path: '/dashboard', element: <Dashboard /> },
      { path: '/profile', element: <Profile /> },
      { path: '/settings', element: <Settings /> },
    ],
  },
]);

处理令牌过期

在保护机制内部或全局拦截器中检查令牌是否过期;令牌过期后退出用户登录,并将其重定向到登录页。

function isTokenValid(token) {
  const payload = JSON.parse(atob(token.split('.')[1]));
  return payload.exp * 1000 > Date.now();
}

function requireAuth() {
  const token = localStorage.getItem('token');
  if (!token || !isTokenValid(token)) throw redirect('/login');
  return token;
}

刷新令牌流程

在因 401 重定向之前,请尝试刷新令牌。只有刷新也失败时,才重定向到登录页。

async function requireAuth() {
  let token = localStorage.getItem('token');
  if (!token || isExpired(token)) {
    token = await refreshToken();
    if (!token) throw redirect('/login');
    localStorage.setItem('token', token);
  }
  return token;
}

在重新加载后保留身份验证状态

将身份验证令牌存储在 localStorage 或 HttpOnly Cookie 中。应用加载时,请在渲染受保护路由之前恢复身份验证状态。

快速检查

在 React Router 中使用基于加载器的身份验证保护机制时,应抛出什么来重定向未通过身份验证的用户?

回顾

您可以使用带有 <Outlet /> 的 PrivateRoute 包装器,或使用会抛出 redirect() 的加载器来保护路由。在导航状态中保留用户原本要访问的 URL,处理加载状态以避免页面闪现,并将受保护的路由归组以避免重复。

常见问题解答

「受保护路由与身份验证守卫」课时是免费的吗?

是的 — 「受保护路由与身份验证守卫」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。

「受保护路由与身份验证守卫」这节课中我会学到什么?

使用包装组件或基于加载器的守卫,将未验证身份的用户重定向到登录页。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 React Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「受保护路由与身份验证守卫」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 React Academy 课中编写并运行代码吗?

能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 嵌套路由与 Outlet 布局
  2. 加载器与操作(数据路由 API)
  3. 受保护路由与身份验证守卫
  4. 管理 URL 搜索参数中的状态
← 返回 React Academy