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

Next.js中如何将Clerk中间件的数据传递至页面或auth对象?

如何从Clerk中间件传递数据到页面或auth对象

Clerk的auth对象是内部封装的实例,无法直接附加自定义数据,但可以通过以下几种可靠方式实现数据传递:

方法一:通过自定义响应头传递

在中间件中创建NextResponse实例,将数据序列化为字符串后存入自定义响应头,再在页面端读取:

中间件代码修改:

import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
import { NextResponse } from 'next/server';

// 示例路由匹配规则,可根据实际项目调整
const isPublicRoute = createRouteMatcher(['/', '/login']);
const isProtectedRoute = createRouteMatcher(['/dashboard']);

export default clerkMiddleware(async (auth, req) => {
  const { userId } = auth();

  const rickAndMorty = await fetch("https://rickandmortyapi.com/api").then(
    (result) => result.json(),
  );

  // 创建响应对象并设置自定义头
  const res = NextResponse.next();
  // 将数据转为JSON字符串存入响应头
  res.headers.set('X-Rick-And-Morty', JSON.stringify(rickAndMorty));

  if (isPublicRoute(req) && userId) {
    return NextResponse.redirect(new URL("/dashboard", req.url));
  }

  if (isProtectedRoute(req)) auth().protect();

  return res;
});

export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};

页面端读取(App Router Server Component):

import { headers } from 'next/headers';

export default async function Page() {
  const headersList = headers();
  const rickAndMortyRaw = headersList.get('X-Rick-And-Morty');
  const rickAndMortyData = rickAndMortyRaw ? JSON.parse(rickAndMortyRaw) : null;

  return <div>{JSON.stringify(rickAndMortyData, null, 2)}</div>;
}

页面端读取(Pages Router getServerSideProps):

export async function getServerSideProps(context) {
  const rickAndMortyRaw = context.res.getHeader('X-Rick-And-Morty');
  const rickAndMortyData = rickAndMortyRaw ? JSON.parse(rickAndMortyRaw) : null;

  return { props: { rickAndMortyData } };
}

方法二:通过Cookie存储数据

如果数据体积较小(不超过4KB),可以将数据存入Cookie,页面端读取Cookie获取数据:

中间件代码修改:

import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
import { NextResponse } from 'next/server';
import { serialize } from 'cookie';

const isPublicRoute = createRouteMatcher(['/', '/login']);
const isProtectedRoute = createRouteMatcher(['/dashboard']);

export default clerkMiddleware(async (auth, req) => {
  const { userId } = auth();

  const rickAndMorty = await fetch("https://rickandmortyapi.com/api").then(
    (result) => result.json(),
  );

  const res = NextResponse.next();
  // 序列化数据为Cookie值
  const cookieValue = serialize('rickAndMortyData', JSON.stringify(rickAndMorty), {
    httpOnly: true, // 可选,禁止前端JS读取,提升安全性
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'strict',
    path: '/',
  });
  res.headers.set('Set-Cookie', cookieValue);

  if (isPublicRoute(req) && userId) {
    return NextResponse.redirect(new URL("/dashboard", req.url));
  }

  if (isProtectedRoute(req)) auth().protect();

  return res;
});

export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};

页面端读取(App Router Server Component):

import { cookies } from 'next/headers';

export default async function Page() {
  const cookieStore = cookies();
  const rickAndMortyRaw = cookieStore.get('rickAndMortyData')?.value;
  const rickAndMortyData = rickAndMortyRaw ? JSON.parse(rickAndMortyRaw) : null;

  return <div>{JSON.stringify(rickAndMortyData, null, 2)}</div>;
}

注意事项

  • 响应头传递数据有大小限制,过大的数据可能被浏览器或服务器截断,适合小体积数据。
  • Cookie存储同样有4KB左右的大小限制,敏感数据建议加密后存储。
  • 如果数据体积较大,建议将数据存入数据库或缓存服务,中间件仅传递数据的唯一标识(如ID),页面端通过标识获取完整数据。

内容的提问来源于stack exchange,提问作者Diego Ulloa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:17:42