浏览文档目录
Agent docs/router/auth-before-load
recipe

用 beforeLoad 保护路由子树

在 pathless layout 中读取类型化认证 Context,阻止未登录用户加载子路由,并保留经过约束的回跳 URL。

View raw Markdown
CONTRACT

执行契约

适用场景
一组 Router 页面必须在任何子 Loader 执行前要求有效登录会话。
不要使用
不要把客户端 beforeLoad 当作服务端资源授权,也不要只靠隐藏导航链接。
前置检查
确认认证状态如何进入类型化 Router Context、私有路由的共同父级以及允许的登录回跳目标。
验证结果
测试未登录直达、登录刷新、会话过期和恶意外部回跳,并证明子 Loader 与服务端入口都在各自边界拒绝未授权请求。
失败模式
若页面先请求私有数据再跳登录,门禁放得太低或异步认证未在父 beforeLoad 中完成;上移到保护子树的最近共同父级。
安全边界
验证 redirect 目标为本站安全路径,防止开放重定向;所有私有 Server Function、Server Route 和数据源必须重新鉴权与授权。
01

决策顺序

先确认认证状态如何进入 Router Context,再选择保护整棵子树的最近 pathless layout。父级 beforeLoad 在子级之前执行;无会话时 throw redirect,有会话时返回最小 user 上下文。不要在每个叶子路由复制检查。

02

最小实现

使用 beforeLoad 参数中的 location.href 记录真实目标。登录处理器只允许站内相对路径或经过同源验证的目标;外部 URL 必须回退到固定首页。

src/routes/_authenticated.tsxtsx
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 />,
})
03

验证矩阵

验证未登录直达不会运行子 Loader;登录用户刷新正常;会话过期后下一次导航回到登录;外部 redirect 被拒绝;服务端数据入口在绕过 UI 直接调用时仍独立返回未授权。

PRIMARY SOURCEShttps://tanstack.com/router/latest/docs/framework/react/guide/authenticated-routeshttps://tanstack.com/router/latest/docs/framework/react/guide/router-context