---
id: authenticated-routes
track: learn
product: router
locale: zh-CN
order: 14
revision: 1
sourceCheckedOn: "2026-08-03"
versionRange: "Router ^1"
verifiedAgainst: "@tanstack/react-router@1.170.18"
contentModel: 2
prerequisites:
  - "理解 Router Context 与 beforeLoad"
  - "已有可读取当前会话的认证服务"
sourceRefs:
  - "https://tanstack.com/router/latest/docs/framework/react/guide/authenticated-routes"
  - "https://tanstack.com/router/latest/docs/framework/react/guide/router-context"
---

# 在加载子路由前确认身份

> 用类型化 Router Context 和 pathless layout 的 beforeLoad 保护一组页面，同时保留正确的登录回跳地址。

**Outcome:** 能建立不会先加载私有子路由的认证门禁，并解释为什么它仍不能替代服务端授权。

## 身份、权限与导航是三件事

认证回答“用户是谁”，授权回答“用户能否访问这个资源”，Router 门禁只负责导航体验。beforeLoad 可以阻止子路由继续加载并跳到登录页，但真正读取或修改私有数据的服务端入口必须再次认证并执行资源级授权。

## 在 pathless layout 集中门禁

父路由 beforeLoad 先于子路由执行；把私有页面放在 `_authenticated` 下面即可复用一处检查。使用回调参数中的 location.href 保存真实目标，不要读取可能落后的 resolvedLocation。登录页必须验证回跳目标属于本站，避免开放重定向。

File: `src/routes/_authenticated.tsx`

```tsx
import { Outlet, createFileRoute, redirect } from '@tanstack/react-router'

export const Route = createFileRoute('/_authenticated')({
  beforeLoad: ({ context, location }) => {
    if (!context.auth.user) {
      throw redirect({
        to: '/login',
        search: { redirect: location.href },
      })
    }

    return { user: context.auth.user }
  },
  component: () => <Outlet />,
})
```

## 把异常与未登录分开

“没有会话”可以稳定跳转登录；认证服务超时、网络失败或配置错误是另一类故障，应进入可观测的错误恢复流程。若在 catch 中处理认证错误，必须重新抛出 Router redirect，不能把有意的控制流吞掉。

> **Note:** 隐藏菜单不是认证；客户端已有的 user 对象也不是服务端权限凭证。

## 实践与验证

### 完成检查点

未登录用户在任何私有子路由 Loader 执行前被重定向，登录用户可以从 Context 得到类型化 user。

### 动手练习

建立 `_authenticated` pathless layout，保护 dashboard 与 settings，并在登录后安全回到原本站内 URL。

### 验证方法

测试未登录直达、已登录刷新、会话过期和恶意外部 redirect；服务端接口还必须独立拒绝无权限请求。

### 常见错误

- 只隐藏导航链接，却允许私有 Loader 和服务端接口直接执行。
- 不验证 redirect 参数就跳转，造成开放重定向。

## Official sources

- https://tanstack.com/router/latest/docs/framework/react/guide/authenticated-routes
- https://tanstack.com/router/latest/docs/framework/react/guide/router-context
