Next.js搭配Node.js(Express)后端无法设置Cookie问题排查
问题分析与解决方案
你的核心问题出在跨域请求配置、代理逻辑错误、Next.js配置覆盖这几个点上,以下是具体修复步骤和生产环境配置方案:
一、本地开发环境修复步骤
1. 修正next.config.js的配置覆盖问题
你之前重复导出了nextConfig,导致rewrites配置被覆盖,代理规则完全没生效。合并配置:
/** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, async rewrites() { return [{ source: "/api/v1/:path*", destination: "http://localhost:8000/api/v1/:path*" }]; } }; module.exports = nextConfig;
2. 前端登录请求改为走代理地址
直接请求后端localhost:8000会触发跨域,必须通过Next.js的代理路径发起请求:
// 登录页面中修改SWR请求地址 const { trigger, isMutating } = useSWRMutation("/api/v1/admins/login", adminLogin);
3. Axios请求添加Cookie携带权限
跨域请求下必须开启withCredentials才能让浏览器保存并携带HTTP-Only Cookie,同时无需手动设置Content-Type(FormData会自动生成正确的头):
const adminLogin = async (url: string, data: any) => { const { arg: { username, password } } = data; let formData = new FormData(); formData.append("username", username); formData.append("password", password); try { const result = await axios.post(url, formData, { withCredentials: true // 关键配置:允许携带Cookie }); console.log(result); return result.data; } catch (error) { const err = error as AxiosError; return err.response!.data; } };
4. 修复API代理的Cookie拦截逻辑
你的代理代码错误地试图从响应体中提取authToken,但后端是通过Set-Cookie头返回token的,需要修改拦截逻辑:
// api/[...path].ts 中的 interceptLoginResponse 函数 function interceptLoginResponse(proxyRes: any, req: any, res: any) { let apiResponseBody = ""; proxyRes.on("data", (chunk: any) => { apiResponseBody += chunk; }); proxyRes.on("end", () => { try { // 从后端响应头提取Set-Cookie const setCookieHeader = proxyRes.headers['set-cookie']; if (setCookieHeader) { const cookies = new Cookies(req, res); // 解析token值 const cookieMatch = setCookieHeader[0].match(/token=([^;]+);/); if (cookieMatch) { const token = cookieMatch[1]; cookies.set("token", token, { httpOnly: true, sameSite: "lax", path: "/", maxAge: 7 * 24 * 60 * 60 // 和后端7天过期时间一致 }); } } // 返回后端原响应数据 res.status(proxyRes.statusCode).json(JSON.parse(apiResponseBody)); resolve(); } catch (err) { reject(err); } }); }
同时修正代理目标地址(避免路径重复):
proxy.web(req, res, { target: "http://localhost:8000", // 原target多了/api/v1,会导致路径重复 autoRewrite: false, selfHandleResponse: isLogin });
二、生产环境(Nginx部署)修改
1. Nginx核心配置
生产环境必须用HTTPS(否则secure属性的Cookie无法生效),同时配置API转发和Cookie传递:
server { listen 80; server_name your-domain.com; # 强制跳转HTTPS return 301 https://$server_name$request_uri; } server { listen 443 ssl; server_name your-domain.com; # SSL证书配置 ssl_certificate /path/to/your/cert.pem; ssl_certificate_key /path/to/your/key.pem; # 前端静态文件托管 location / { root /path/to/nextjs-production-build; try_files $uri $uri/ /index.html; } # API请求转发到后端 location /api/v1/ { proxy_pass http://localhost:8000/api/v1/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 确保Cookie正确传递 proxy_cookie_path / "/; secure; SameSite=Lax"; proxy_pass_header Set-Cookie; } }
2. 后端Express的Cookie配置升级
生产环境下需要开启secure属性(仅HTTPS生效),同时完善Cookie属性:
res.cookie("token", jwt, { httpOnly: true, secure: true, // 生产环境必须开启 sameSite: "Lax", path: "/", maxAge: 7 * 24 * 60 * 60 });
3. 前端生产环境注意事项
- 所有API请求必须使用同域名路径(如
/api/v1/xxx),禁止直接请求后端IP/域名 - 确保生产构建时
next.config.js的代理规则已正确配置(或直接依赖Nginx转发)
内容的提问来源于stack exchange,提问作者user10033434
相关产品推荐
相关产品推荐

