跨域生产环境下Next.js中间件无法读取JWT Cookie问题
问题背景
我开发的应用前端基于Next.js,后端采用Node.js+Express.js架构,通过Next.js中间件实现JWT鉴权。本地开发阶段,前后端运行在localhost不同端口(前端http://localhost:3000、后端http://localhost:8001),所有功能正常。但部署到生产环境后,前端域名是https://frontend.com,后端域名是https://backend.com:8001,此时Next.js中间件无法读取Cookie中的JWT令牌,导致鉴权授权功能失效。
相关代码
Next.js 中间件代码
// next.js middleware import { NextResponse } from "next/server"; import { jwtVerify } from "jose"; // ... 其他导入 ... const secret = process.env.SECRET; async function verify(token, secret) { const { payload } = await jwtVerify(token, new TextEncoder().encode(secret)); return payload; } export default async function middleware(request) { const url = request.url; const nextUrl = request.nextUrl.clone(); // ... 中间件其他逻辑 ... // 权限校验示例函数 const checkAccess = async (allowedRole) => { const jwt = request.cookies.get('token')?.value; if (!jwt) { nextUrl.pathname = '/'; return NextResponse.rewrite(nextUrl); } try { const verification = await verify(jwt, secret); if (verification.Role === allowedRole) { return NextResponse.next(); } else { throw new Error("ACCESS DENIED"); } } catch (e) { // 错误处理 // ... } }; // 角色校验 if (url.includes("/dashboard/teacher")) { return checkAccess('Teacher'); } // ... 其他校验逻辑 ... return NextResponse.next(); };
后端登录接口的Cookie配置
function getDomainURL(){ switch (process.env.NODE_ENV){ case ('production'): return '.frontend.com'; case ('development'): return 'localhost' } } const COOKIE_OPTIONS = { httpOnly: true, path: "/", sameSite: 'None', // 允许跨域请求携带Cookie secure: true, // sameSite为None时必须设置为true domain: getDomainURL() }; res.setHeader("Set-Cookie", serialize("token", token, COOKIE_OPTIONS)); function getOriginURL(){ switch (process.env.NODE_ENV){ case ('production'): return 'https://www.frontend.com'; case ('development'): return 'http://localhost:3000' } } let originURL = getOriginURL() app.use(cors({ origin: originURL, credentials: true, }))
解决步骤
1. 修正Cookie的Domain配置
生产环境中,后端设置的Cookie domain为.frontend.com,需确保前端域名frontend.com和www.frontend.com都能匹配该Cookie:
- 现代浏览器中顶级域名前缀的点(
.)可选,但为兼容老版本浏览器可保留 - 确认后端设置的domain与前端实际域名完全匹配,避免因
www前缀导致的Cookie无法读取
2. 强制前端请求携带Credentials
前端调用后端登录接口时,必须显式设置credentials: 'include',确保浏览器在跨域请求中携带Cookie:
// 前端登录请求示例 fetch('/api/login', { method: 'POST', credentials: 'include', // 关键配置 body: JSON.stringify(loginData) })
3. 配置Next.js跨域代理
在Next.js项目的next.config.js中添加路由重写规则,将前端API请求转发到后端,避免直接跨域请求:
// next.config.js /** @type {import('next').NextConfig} */ const nextConfig = { async rewrites() { return [ { source: '/api/:path*', destination: 'https://backend.com:8001/api/:path*', }, ] }, } module.exports = nextConfig
配置后前端请求/api/login会被转发到后端对应接口,此时请求属于同域(前端域名),Cookie会被正常携带,Next.js中间件即可读取。
4. 校验SameSite与Secure属性
- 生产环境下
sameSite: 'None'必须配合secure: true,且必须使用HTTPS协议,否则浏览器会拒绝存储Cookie - 本地开发阶段若使用HTTP,需将
secure设为false,sameSite设为Lax或Strict,避免浏览器阻止Cookie
5. 确认Cookie作用域
确保Cookie的path设置为"/",保证前端域名下所有路径都能访问该Cookie。
验证方法
- 登录后,在浏览器开发者工具的Application > Cookies > https://frontend.com中查看是否存在
tokenCookie - 访问需要鉴权的路由(如
/dashboard/teacher),在Next.js中间件中打印request.cookies,确认能获取到token值
内容的提问来源于stack exchange,提问作者Joaquín Caballero
相关产品推荐
相关产品推荐

