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
相关产品推荐
相关产品推荐

