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 授权策略。