EC2上Next.js中间件无法获取Express设置的Http-only Cookie问题
问题背景
在AWS EC2上部署了两个服务:
- 基于Next.js 13的前端服务,域名:
https://www.example.com - 基于Express的后端服务,域名:
https://api.example.com
后端设置Http-only Cookie的代码:
response.cookie("refreshToken", refreshToken, { maxAge: 3.154e10, // 1 year httpOnly: true, secure: true, sameSite: 'none', domain: process.env.CLIENT_SERVER, // Set to your domain path: '/' // Accessible to all paths });
前端在middleware.ts中获取Cookie的代码:
function parseCookies(cookieHeader: any) { const cookies: any = {}; if (cookieHeader) { const items = cookieHeader.split(";"); items.forEach((item: string) => { const [key, value] = item.split("="); cookies[key.trim()] = value.trim(); }); } return cookies; } export async function middleware(request: NextRequest) { try { const cookieHeader = request.headers.get("cookie") || ""; const cookies = parseCookies(cookieHeader); const accessToken = cookies["accessToken"]; const refreshToken = cookies["refreshToken"];
问题现象:本地运行前端访问EC2后端API时,Cookie可正常获取;但前后端均部署在EC2上时,前端获取的Cookie为undefined。
排查与解决方案
1. 修正Cookie的domain配置
后端设置的domain参数必须为父域名,才能让www.example.com和api.example.com两个子域共享Cookie。当前如果process.env.CLIENT_SERVER的值是www.example.com,会导致只有www子域能识别Cookie,api子域设置的Cookie无法被前端读取。
修改后端代码的domain配置:
domain: ".example.com", // 确保环境变量的值为带前缀点的父域名
2. 确保前端请求开启withCredentials
跨子域请求时,前端必须显式配置携带凭证,否则浏览器不会传递Cookie。无论是用fetch还是Axios,都要开启对应选项:
fetch示例:
fetch('https://api.example.com/auth/login', { method: 'POST', credentials: 'include', // 其他请求配置 });
- Axios示例:
axios.post('https://api.example.com/auth/login', requestData, { withCredentials: true });
3. 验证HTTPS配置完整性
Cookie的secure: true要求请求必须通过HTTPS传输,需确认:
- 前后端域名都配置了有效SSL证书(可通过AWS Certificate Manager配合ALB/CloudFront实现)
- 前端HTTPS页面没有调用HTTP协议的后端接口(避免混合内容导致Cookie被拒绝)
- EC2服务或前端代理(如Nginx)正确处理HTTPS流量,没有降级为HTTP
4. 排查Next.js Middleware的请求上下文
在Middleware中添加日志,确认cookie头是否被正确传递:
export async function middleware(request: NextRequest) { try { console.log("Received cookie header:", request.headers.get("cookie")); const cookieHeader = request.headers.get("cookie") || ""; const cookies = parseCookies(cookieHeader); // 后续逻辑 } catch (err) { console.error("Middleware error:", err); } }
如果日志中没有refreshToken,说明Cookie未被浏览器携带,回到前三点重新排查;如果Cookie存在但解析失败,检查parseCookies函数的分割逻辑是否有问题(比如Cookie值包含=符号的情况)。
5. 检查浏览器Cookie存储
打开浏览器开发者工具(Application -> Cookies -> https://www.example.com),查看是否存在refreshToken:
- 若不存在:重点检查后端Cookie的
domain、secure、sameSite参数配置 - 若存在但Middleware无法读取:确认Next.js配置中未限制Cookie传递,可在
next.config.js中添加跨域凭证允许:
// next.config.js module.exports = { async headers() { return [ { source: '/(.*)', headers: [ { key: 'Access-Control-Allow-Credentials', value: 'true' }, { key: 'Access-Control-Allow-Origin', value: 'https://www.example.com' }, ], }, ]; }, };
内容的提问来源于stack exchange,提问作者Naveed Ali Rehmani
相关产品推荐
相关产品推荐

