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

Next.js Server Actions:如何获取中间件中设置的自定义参数?

最佳实践方案

在Next.js中实现中间件认证后向Server Action传递用户数据,推荐以下两种落地方案:

方案1:加密请求头传递用户标识(轻量场景)

这种方式适合不需要存储大量用户信息的场景,核心是通过加密的自定义请求头传递用户唯一标识,避免前端篡改。

1. 中间件处理逻辑

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { encrypt } from '@/lib/encryption'; // 自定义加密工具(可使用crypto模块实现)

export async function middleware(request: NextRequest) {
  // 执行你的身份验证逻辑,比如从Cookie读取token并验证,获取用户数据
  const user = await authenticateUser(request);
  
  if (!user) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  // 加密用户ID,防止恶意篡改
  const encryptedUserId = encrypt(user.id);
  const requestHeaders = new Headers(request.headers);
  requestHeaders.set('x-encrypted-user-id', encryptedUserId);

  return NextResponse.next({
    request: { headers: requestHeaders }
  });
}

2. Server Action读取逻辑

// Server Action
import { headers } from 'next/headers';
import { decrypt } from '@/lib/encryption'; // 对应解密工具

export async function getProjectsByUser(): Promise<PrismaProject[]> {
  const encryptedUserId = headers().get('x-encrypted-user-id');
  if (!encryptedUserId) throw new Error('用户未认证');

  const userId = decrypt(encryptedUserId);
  // 直接用用户ID查询关联项目,无需重复调用getUser()
  const projects = await prisma.project.findMany({
    where: { user_id: userId },
    include: {
      Document: true,
      Conversation: { include: { Message: true } }
    }
  });

  return projects;
}

方案2:Session存储用户信息(推荐,安全性更高)

如果项目已使用Session(如iron-session、NextAuth),优先用这种方式,Session数据加密存储在Cookie中,无需手动处理加密逻辑,安全性更强。

1. 中间件处理逻辑

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { getIronSession } from 'iron-session';
import { sessionOptions } from '@/lib/session'; // 你的Session配置(含加密密钥)

export async function middleware(request: NextRequest) {
  const res = NextResponse.next();
  const session = await getIronSession(request, res, sessionOptions);

  // 验证用户,无有效Session则执行认证逻辑
  if (!session.user) {
    const user = await authenticateUser(request);
    if (!user) return NextResponse.redirect(new URL('/login', request.url));
    // 仅存储非敏感用户字段(如ID、用户名)
    session.user = { id: user.id, username: user.username };
    await session.save();
  }

  return res;
}

2. Server Action读取逻辑

// Server Action
import { getIronSession } from 'iron-session';
import { sessionOptions } from '@/lib/session';
import { cookies } from 'next/headers';

export async function getProjectsByUser(): Promise<PrismaProject[]> {
  const session = await getIronSession(cookies(), sessionOptions);
  if (!session.user?.id) throw new Error('用户未认证');

  const projects = await prisma.project.findMany({
    where: { user_id: session.user.id },
    include: {
      Document: true,
      Conversation: { include: { Message: true } }
    }
  });

  return projects;
}

核心注意事项

  • 禁止在请求头或Session中存储敏感数据(如密码、手机号),仅保留必要的用户标识或非敏感字段。
  • 无论用哪种方案,Server Action中都要再次校验用户标识的有效性,避免绕过中间件的恶意请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 17:02:40