跳到主要内容

6.3.3 React 路由与权限守卫

前端路由负责页面切换,权限守卫负责控制用户体验。真正的权限必须由后端保证,但前端也应避免未登录用户进入需要登录的页面。

学习目标

  • 能设计公开页面和受保护页面。
  • 能根据登录状态控制路由访问。
  • 能处理 401 和 403 响应。
  • 能理解前端守卫和后端授权的关系。

应用场景

  • 未登录用户访问 /todos 时跳转登录页。
  • 登录后回到原本要访问的页面。
  • 普通用户访问管理页时展示无权限页面。
  • Token 过期后清理登录态。

登录态模型

type AuthState =
| {status: 'anonymous'}
| {status: 'authenticated'; user: CurrentUser};

type CurrentUser = {
id: string;
displayName: string;
roles: string[];
};

权限守卫示例

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

type ProtectedRouteProps = {
auth: AuthState;
requiredRole?: string;
};

export function ProtectedRoute({auth, requiredRole}: ProtectedRouteProps) {
const location = useLocation();

if (auth.status === 'anonymous') {
return <Navigate to="/login" state={{from: location}} replace />;
}

if (requiredRole && !auth.user.roles.includes(requiredRole)) {
return <Navigate to="/forbidden" replace />;
}

return <Outlet />;
}

API 错误处理

export async function request(input: RequestInfo, init?: RequestInit) {
const response = await fetch(input, init);

if (response.status === 401) {
throw new AuthError('unauthorized');
}

if (response.status === 403) {
throw new AuthError('forbidden');
}

if (!response.ok) {
throw new Error('请求失败');
}

return response;
}

重点难点

  • 前端守卫只是体验层,不能替代后端授权。
  • 登录后跳回来源页面能明显提升体验。
  • 401 是未登录,403 是已登录但无权限,两者处理不同。
  • 角色和权限最好来自后端当前用户接口,不要写死在前端。

常见误区

误区推荐做法
隐藏按钮就等于授权后端 API 必须执行授权
401 和 403 混用分别处理登录过期和权限不足
把权限规则散落在页面统一封装路由守卫和权限判断函数

练习

  • /todos 增加登录守卫。
  • /admin 增加管理员角色守卫。
  • API 返回 401 时清理登录态并跳转登录页。

延伸阅读

  • React Router。
  • SPA 认证模式。
  • ASP.NET Core 授权策略。