跨站携带凭证请求失效 Next.js+Nest.js跨域Cookie不传递问题
核心故障点
你的axios和基础CORS配置逻辑是对的,问题出在Fastify适配器的默认行为和Cookie配置的兼容问题,导致浏览器根本没把后端返回的token Cookie存下来,后续请求自然无法携带。
修复步骤
1. 修正Fastify适配器下的CORS配置
Nest搭配Fastify适配器时,默认的enableCors不会给3xx重定向响应、OPTIONS预检响应自动追加合法的CORS头,会直接拦截重定向响应里的Set-Cookie指令。把原有CORS配置替换为如下逻辑:
app.enableCors({ origin: (origin, callback) => { const allowList = ["http://localhost:3000", "https://my-app.vercel.app"]; if (!origin || allowList.includes(origin)) return callback(null, true); return callback(new Error("CORS origin not allowed"), false); }, credentials: true, preflightContinue: false, optionsSuccessStatus: 204, });
同时把OAuth流程最后跳转前端的重定向状态码改为303,避免浏览器对302重定向的Cookie拦截:
// 原有重定向逻辑替换为明确指定303状态码 res.redirect(303, "https://my-app.vercel.app/dashboard")
2. 按环境调整Cookie属性
你当前的Cookie配置存在环境兼容问题,会导致本地调试和部分浏览器场景下Cookie被丢弃,按如下逻辑修改:
res.setCookie( "token", this.jwtService.sign({ id: user.id, email: user.email }), { path: "/", // 生产环境启用secure,本地HTTP环境关闭 secure: process.env.NODE_ENV === "production", // 生产环境跨站用none,本地调试用lax sameSite: process.env.NODE_ENV === "production" ? "none" : "lax", httpOnly: true, // 必须加明确的过期时间,无过期时间的会话Cookie会被Safari、Chrome隐私模式直接拦截 maxAge: 7 * 24 * 60 * 60 * 1000, } );
注意:跨顶级域名场景不要手动设置
domain属性,留空即可,错误的domain配置会直接导致Cookie无法存储。
3. 验证Cookie存储状态
改完配置重新走一遍OAuth流程,打开浏览器开发者工具做两步校验:
- 切到Application -> Cookies面板,选中后端Railway域名,确认是否存在
token条目。如果不存在,检查后端响应头里是否有Set-Cookie字段,以及响应头是否携带匹配当前源的Access-Control-Allow-Credentials: true - 如果Cookie存在,发起接口请求时查看Request Headers,只要
withCredentials: true配置生效,浏览器会自动携带符合规则的Cookie,不需要手动在请求头里添加Cookie字段
避坑提示
- 不要手动在axios的headers里写
Cookie字段,浏览器会直接拦截跨站请求中手动设置的Cookie头,属于强制安全策略,无法绕过 - Chrome高版本默认拦截第三方Cookie时,可以点击地址栏左侧锁形图标 -> 站点设置,给当前站点开放第三方Cookie权限做本地调试,生产环境只要配置了
SameSite=None; Secure就不会被默认拦截
内容的提问来源于stack exchange,提问作者tavin-dev
相关产品推荐
相关产品推荐

