Next.js 14线上环境中间件无法获取Cookie的问题及解决咨询
可能的问题原因
- Cookie属性配置缺失:线上为HTTPS环境,若
_rrCookie未设置Secure属性,浏览器会拒绝在HTTPS请求中携带该Cookie;SameSite属性设置不合理(如Strict)也会导致跨域/子域场景下Cookie无法被携带。 - Cookie域名不匹配:设置Cookie时指定的
Domain属性与线上部署的域名不一致,浏览器不会将Cookie发送到服务器。 - 环境变量不一致:解密函数
decryptCookieData依赖的密钥(如JWT密钥)线上环境与本地不匹配,导致解密失败,表现为无法获取有效Cookie数据。 - 中间件路由匹配问题:部署平台(如Vercel)的边缘配置或项目的
basePath设置,导致中间件的matcher路径与实际请求路径不匹配,中间件未正确执行。
修复方案
1. 修正Cookie的属性配置
在设置_rr Cookie时,根据环境动态配置必要属性:
// 示例:在API路由/登录逻辑中设置Cookie import { NextResponse } from 'next/server'; export function POST() { // 生成加密后的Cookie值 const encryptedValue = 'your-encrypted-jwt'; const isProduction = process.env.NODE_ENV === 'production'; const response = NextResponse.json({ success: true }); response.cookies.set('_rr', encryptedValue, { httpOnly: true, // 防止XSS攻击 secure: isProduction, // 线上HTTPS环境必须开启 sameSite: isProduction ? 'lax' : 'lax', // 跨域场景需设为'none',且必须配合Secure domain: isProduction ? '.your-production-domain.com' : undefined, // 多子域场景设置根域 path: '/', maxAge: 60 * 60 * 24 * 7, // 按需设置有效期 }); return response; }
2. 确保环境变量一致性
- 检查部署平台(如Vercel、Netlify)的环境变量配置,确保解密所需的密钥(如
JWT_SECRET)与本地.env文件中的值完全一致。 - 避免将密钥硬编码到代码中,始终通过环境变量注入。
3. 优化中间件的错误处理与日志
添加错误捕获和日志输出,方便线上排查问题:
import { decryptCookieData } from '@Utils/decrypt'; import { JwtPayload } from 'jsonwebtoken'; import type { NextRequest } from 'next/server'; import { NextResponse } from 'next/server'; import { paths } from '@/constants'; import { Role } from '@/enums/role'; export function middleware(request: NextRequest) { const { pathname } = request.nextUrl; const cookie = request.cookies.get('_rr'); // 线上环境可通过平台日志工具查看该输出 console.log('Middleware: _rr cookie exists:', !!cookie?.value); let decrypted: JwtPayload | null = null; if (cookie?.value) { try { decrypted = decryptCookieData(cookie.value); } catch (error) { console.error('Middleware: Decrypt _rr cookie failed:', error); } } // 无有效解密数据直接跳转 if (!decrypted) { return NextResponse.redirect(new URL(paths.notHaveAccessPage, request.url)); } // 超级管理员权限校验 if (decrypted.role === Role.SUPPER_ADMIN) { return NextResponse.next(); } // 普通管理员权限校验 const allowedAdminPaths = [paths.upload, paths.management, paths.adminDashboard]; if (allowedAdminPaths.includes(pathname) && decrypted.role === Role.ADMIN) { return NextResponse.next(); } return NextResponse.redirect(new URL(paths.notHaveAccessPage, request.url)); } export const config = { matcher: ['/admin/:path*'], };
4. 验证中间件路由匹配
- 若项目配置了
basePath,需在config.matcher中补充对应路径:export const config = { matcher: ['/admin/:path*', '/your-base-path/admin/:path*'], }; - 检查部署平台的边缘函数配置,确保中间件被正确部署并生效。
内容的提问来源于stack exchange,提问作者Đạt Huỳnh
相关产品推荐
相关产品推荐

