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

Next.js 14路由处理器设置Cookie失效问题求助

Next.js 14 路由处理器Cookie设置失效问题解决

问题根源

你现在的核心问题是登录页面是Server Component,里面的fetch是在服务器端执行的,控制台打印的res.headers.getSetCookie()是服务器端fetch请求拿到的响应头,浏览器根本没接收到这个Set-Cookie——因为服务器端直接执行了redirect('/'),浏览器最终收到的是跳转响应,完全没接触到登录接口返回的Set-Cookie头,自然不会保存Cookie。

修复方案

方案1:将登录逻辑移到客户端组件(推荐)

把登录页面转为客户端组件,让fetch在浏览器端执行,这样浏览器能直接接收Set-Cookie头并保存:

// app/auth/login/page.tsx
'use client'; // 转为客户端组件
import { useSearchParams, useRouter } from 'next/navigation';
import { useEffect } from 'react';

import { LoginPage } from 'common';

const Login = () => {
  const searchParams = useSearchParams();
  const router = useRouter();

  useEffect(() => {
    const loginCode = searchParams.get('code');
    if (loginCode) {
      fetch(`/auth/login/post?code=${loginCode}`, {
        method: 'POST',
      }).then(() => {
        router.push('/');
      });
    }
  }, [searchParams, router]);

  return <LoginPage />;
};

export default Login;

同时修正路由处理器的Cookie设置逻辑,不要混用cookieStore.set和手动Set-Cookie头,用Next.js提供的NextResponse更规范:

// app/auth/login/post/route.ts
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';

import type { TokenResponseLoginType } from 'types';

export async function POST(request: NextRequest) {
  try {
    // ... 你的token获取逻辑
    const tokenData: TokenResponseLoginType = await res.json();

    const response = NextResponse.redirect(new URL('/', request.url));
    // 按需配置Cookie属性
    response.cookies.set('refresh_token', tokenData.refreshToken, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
    });
    response.cookies.set('access_token', tokenData.accessToken, {
      httpOnly: false, // 前端需要读取则设为false,否则设为true
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
    });

    return response;
  } catch (e) {
    return NextResponse.redirect(new URL('/auth/login', request.url));
  }
}

方案2:直接在路由处理器中完成跳转+Cookie设置

如果不想修改客户端组件,可以调整登录流程:把/auth/login?code=xxx作为路由处理器,直接在服务器端处理登录、设置Cookie后跳转,不需要页面端发起fetch:

// app/auth/login/route.ts(新增该路由处理登录逻辑)
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

import type { TokenResponseLoginType } from 'types';

export async function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams;
  const loginCode = searchParams.get('code');
  
  if (!loginCode) {
    return NextResponse.redirect(new URL('/auth/login/page', request.url)); // 指向纯登录页面
  }

  try {
    // ... 你的token获取逻辑
    const tokenData: TokenResponseLoginType = await res.json();

    const response = NextResponse.redirect(new URL('/', request.url));
    response.cookies.set('refresh_token', tokenData.refreshToken, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
    });
    response.cookies.set('access_token', tokenData.accessToken, {
      httpOnly: false,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
    });

    return response;
  } catch (e) {
    return NextResponse.redirect(new URL('/auth/login/page', request.url));
  }
}

// 原登录页面改为纯展示组件
// app/auth/login/page.tsx
import { LoginPage } from 'common';

const LoginPageWrapper = () => {
  return <LoginPage />;
};

export default LoginPageWrapper;

关键注意点

  • Server Component里的fetch是服务器端执行的,浏览器无法获取其响应头,不能用这种方式设置浏览器Cookie
  • 不要同时使用cookies().set()和手动设置Set-Cookie头,会导致冲突
  • Cookie的secure属性在开发环境(http://localhost)要设为false,生产环境(https)设为true,否则浏览器会拒绝保存
  • httpOnly设为true的Cookie无法被前端JS读取,适合存refresh_token;access_token如果需要前端使用,设为false

内容的提问来源于stack exchange,提问作者이승제

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 03:10:16