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

Nest.js部署至Heroku生产环境后res.cookie()无法设置HTTP Cookie问题求助

跨域Cookie失效问题排查与解决方案

我帮你梳理下本地正常但部署到Vercel/Heroku后Cookie失效的核心问题,主要集中在CORS配置一致性、跨域Cookie的域名绑定和Next.js服务端渲染的Cookie获取逻辑这几个点,咱们一步步解决:


1. 先修复Nest.js的CORS配置冲突

你现在的代码里同时用了NestFactory.create的cors: true和app.enableCors(),这会导致配置冲突,而且登录路由里手动设置CORS头也会和全局配置重复。

修改main.ts:

async function bootstrap() {
 const app = await NestFactory.create(AppModule, {
 logger: new LoggerService(),
 // 删掉这里的 cors: true,避免和全局配置冲突
 });
 app.use(cookieParser());
 // 统一用全局CORS配置,明确指定允许的Vercel域名
 app.enableCors({
 origin: ['https://your-vercel-domain.vercel.app'], // 替换成你的实际Vercel域名
 credentials: true,
 allowedHeaders: ['Content-Type', 'Authorization'],
 methods: ['GET', 'POST', 'PUT', 'DELETE'],
 });
 ...
 await app.listen(process.env.PORT || 5000);
}
bootstrap();

然后删除登录路由里手动设置的CORS头:

// 登录路由中去掉这两行,全局CORS会自动处理
// .set("Access-Control-Allow-Credentials", "true")
// .set("Access-Control-Allow-Origin", origin)

2. 调整Cookie策略:跨域Cookie vs 前端存储Token

方案A:坚持用后端设置跨域Cookie

如果一定要用后端设置Cookie,必须确保Cookie的domain和path配置正确,让浏览器能在跨域请求时带上:

res.cookie("accessToken", accessToken, {
 expires: new Date(new Date().getTime() + 60 * 1000 * 60 * 2),
 sameSite: "none",
 secure: true,
 httpOnly: false, // 如果你需要前端读取,这个设置是对的,但有安全风险
 domain: "your-api.herokuapp.com", // 替换成你的Heroku后端域名
 path: "/", // 确保所有路径都能携带Cookie
});

⚠️ 注意:这种方式下,Next.js的getServerSideProps无法直接读取到这个Cookie——因为Cookie绑定在Heroku域名下,Vercel的服务端无法获取用户浏览器中属于其他域名的Cookie,只有前端请求Heroku后端时才会自动带上。

方案B:前端存储Token到自身域名Cookie(更推荐)

这种方式能让Next.js服务端正常读取Cookie,逻辑更可控:

  • 后端修改:登录路由不再设置Cookie,直接返回Token:
async verify(
 @Body() method: VerificationDto,
 @Req() req: Request,
 @Res({ passthrough: true }) res: Response
) {
 const { accessToken, refreshToken } = await this.userService.verifyLogin(method);
 // 去掉所有setCookie相关代码
 return { accessToken, refreshToken };
}
  • 前端修改:登录成功后用nookies把Token存到Vercel域名的Cookie:
// Axios登录请求的处理逻辑
verifyLogin({ code, email }).then(response => {
  const { accessToken } = response.data;
  nookies.set(null, 'accessToken', accessToken, {
    maxAge: 60 * 60 * 2, // 和后端过期时间保持一致
    path: '/',
    secure: true,
    sameSite: 'lax',
    domain: '.vercel.app', // 替换成你的Vercel域名
  });
  // 跳转到首页或其他需要权限的页面
});
  • 添加Axios拦截器:自动在请求头带上Token,替代Cookie传递:
axios.interceptors.request.use(config => {
  const cookies = nookies.get(null);
  if (cookies.accessToken) {
    config.headers.Authorization = `Bearer ${cookies.accessToken}`;
  }
  return config;
});

3. 修复Next.js的Cookie读取逻辑

修改authenticate函数,确保能正确读取前端域名下的Cookie:

export const authenticate = (
 getServerSidePropsInner: GetServerSideProps = async () => ({ props: {} })
) => {
 const getServerSideProps: GetServerSideProps = async ctx => {
 const cookies = nookies.get(ctx);
 const accessToken = cookies.accessToken;
 if (!accessToken) {
 console.log("no cookie found");
 redirect(ctx, loginRoute);
 return { props: {} };
 }
 console.log(accessToken);
 let user = null;
 try {
 user = {
 accessToken,
 ...(jwtDecode(accessToken as string) as object),
 };
 } catch (e) {
 console.log(e);
 redirect(ctx, loginRoute);
 }
 const result = await getServerSidePropsInner(ctx);
 return {
 ...result,
 props: {
 user,
 //@ts-ignore
 ...result.props,
 },
 };
 };
 return getServerSideProps;
};

4. 最后验证几个关键点

  1. 检查HTTPS:确保Heroku和Vercel的服务都是HTTPS(两者默认都是,不用额外配置),secure: true的Cookie只能在HTTPS环境下生效。
  2. 浏览器Cookie检查:登录后打开Chrome DevTools → Application → Cookies,查看对应域名下是否存在accessToken。
  3. 请求头检查:在Network标签里查看后续请求,确认Authorization头(或Cookie)是否正确携带。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 18:02:38