You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js App Router中如何将Middleware的数据传递到page.tsx?

Next.js App Router中如何将Middleware的数据传递到page.tsx?

兄弟,我太懂你折腾好几个小时的痛苦了😅!在Next.js App Router里,Middleware和Server Component的数据流逻辑确实和旧的Pages Router不太一样,我结合你的代码给你几个靠谱的解决方案:

方案一:最推荐!直接在Server Component里获取用户数据(利用Middleware的前置校验)

你的Middleware已经帮你把无效请求(没有session-token或者token失效)都重定向到首页了,所以能进入/cfa页面的请求,session-token肯定是有效的。那咱完全不用费劲在Middleware和页面之间传数据,直接在page.tsx(默认是Server Component)里读取cookie、调用getUser就行,代码逻辑还更顺:

修改你的page.tsx:

import { FormCreateLocation } from "@/components/forms/FormCreateLocation";
import { Location } from "@/components/resources/Location";
import { getUser } from "@/lib/getUser";
import { cookies } from "next/headers"; // 注意这里导入的是next/headers,不是client目录下的

export default async function Home() {
  // 直接在页面里读取session-token
  const sessionToken = cookies().get('session-token')?.value;
  
  // 因为Middleware已经做了校验,这里sessionToken肯定有值,不用再处理重定向
  const userRequest = await getUser(sessionToken!);
  const userJson = await userRequest.json();

  return (
    <main className="">
      {/* 把用户数据传给需要的组件 */}
      <FormCreateLocation user={userJson} />
      <div className="p-4">
        {/* 直接使用用户数据 */}
        <h2>欢迎回来,{userJson.email}!</h2>
        <h2>Select a Location</h2>
        <ul>
          <Location _id="0333333333" name="Chick-fil-A Highway 22" number="03444" />
          <Location _id="33222222222" name="Chick-fil-A Midtown" number="03253" />
        </ul>
      </div>
    </main>
  );
}

这个方案完全符合Next.js App Router的设计理念——Server Component本来就是用来在服务器端获取数据的,而且Middleware的前置校验已经帮我们过滤了无效请求,页面里不用再处理错误分支,代码简洁又可靠。

方案二:将用户数据存入加密Cookie(适合不想重复调用API的场景)

如果你确实想在Middleware里把用户数据传递到页面,可以把用户数据加密后存入Cookie,然后在页面里读取解密。注意一定要加密,不然敏感信息会暴露在浏览器里!

第一步:修改Middleware

import { NextRequest, NextResponse } from "next/server"
import { getUser } from "./lib/getUser";
// 你需要自己实现加密/解密函数,比如用Node.js的crypto模块
import { encrypt } from "./lib/encrypt";

export async function middleware(request: NextRequest) {
  const sessionToken = request.cookies.get('session-token')

  if (!sessionToken) {
    return NextResponse.redirect(new URL('/', request.url))
  }

  const userRequest = await getUser(sessionToken.value)
  if (userRequest.status !== 200) {
    return NextResponse.redirect(new URL('/', request.url))
  }

  const userJson = await userRequest.json()
  // 加密用户数据
  const encryptedUser = encrypt(JSON.stringify(userJson))
  
  // 创建响应并设置加密后的Cookie
  const response = NextResponse.next()
  response.cookies.set('user-data', encryptedUser, {
    httpOnly: true, // 禁止前端JS读取,提升安全性
    secure: process.env.NODE_ENV === 'production', // 生产环境下仅HTTPS传输
    sameSite: 'strict',
    path: '/cfa' // 仅在/cfa路径下生效
  })
  return response
}

export const config = {
  matcher: "/cfa",
}

第二步:修改page.tsx读取Cookie

import { FormCreateLocation } from "@/components/forms/FormCreateLocation";
import { Location } from "@/components/resources/Location";
import { decrypt } from "@/lib/decrypt"; // 对应加密的解密函数
import { cookies } from "next/headers";
import { redirect } from "next/navigation";

export default async function Home() {
  const encryptedUser = cookies().get('user-data')?.value;
  
  // 兜底处理(理论上Middleware已经拦截了无效请求)
  if (!encryptedUser) {
    redirect('/');
  }
  
  // 解密并解析用户数据
  const userJson = JSON.parse(decrypt(encryptedUser));

  return (
    <main className="">
      <FormCreateLocation user={userJson} />
      <div className="p-4">
        <h2>欢迎回来,{userJson.email}!</h2>
        <h2>Select a Location</h2>
        <ul>
          <Location _id="0333333333" name="Chick-fil-A Highway 22" number="03444" />
          <Location _id="33222222222" name="Chick-fil-A Midtown" number="03253" />
        </ul>
      </div>
    </main>
  );
}

为什么你之前的方法没生效?

你尝试的设置自定义Header、修改NextRequest对象这些方式,在App Router里不太可靠:

  • 自定义Header:Next.js在处理请求时,Middleware设置的自定义Header可能不会被传递到Server Component的请求上下文里(因为内部会重构请求);
  • 修改NextRequest:Middleware里的Request实例是临时的,页面拿到的是新的Request对象,所以修改后的数据传不过去。

总的来说,方案一是最省心的,推荐优先使用!

备注:内容来源于stack exchange,提问作者Phillip England

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 09:34:43