部署至Vercel后请求头未携带Cookie的问题排查
本地开发时,后端运行在http://localhost:3000,前端React运行在http://localhost:8000,所有接口正常。将后端部署到Vercel(地址:https://blog-app-server-red.vercel.app/)后,无需Cookie的路由正常,但需要Cookie(token)的路由失效,请求头未携带Cookie,本地环境则正常。
前端React代码
const getProfilePic = async ()=>{ try { const response = await fetch('https://blog-app-server-red.vercel.app/user/'+userId , { credentials : 'include', headers: { "Content-Type": "application/json", "Access-Control-Allow-Credentials": true, } })
后端Express代码
app.get('/user/:id' , async (req, res)=>{ try { const {token} = req.cookies; const {id} = req.params; if(token){ jwt.verify(token , process.env.JWT_KEY , {} , async (err , info)=>{ if(err){ throw "Wrong Token ! Access Denied" } const user = await User.findById(id).select('-password'); res.status(200).json(user); }); } else{ res.status(400).json({error : "Unauthorized !!!"}) } } catch (error) { res.status(400).json({error}); } })
后端CORS中间件代码
app.use(cors({credentials : true , origin : 'http://localhost:3000'}));
问题原因与解决方案
核心原因
- CORS origin配置不匹配:后端CORS仅允许
http://localhost:3000,但部署后前端域名(包括本地测试的http://localhost:8000)不在允许列表内,浏览器因同源策略阻止跨域Cookie携带。 - Cookie属性未适配跨域场景:本地开发时域名均为localhost,Cookie默认可跨端口携带;部署后后端是HTTPS的
vercel.app域名,Cookie需设置secure: true和sameSite: 'None'才能在跨域请求中被浏览器携带。 - 前端请求头冗余配置:
Access-Control-Allow-Credentials是后端响应头,前端请求中设置该字段无意义,反而可能干扰请求逻辑。
具体修复步骤
更新CORS配置:
动态配置允许的前端域名,覆盖本地和生产环境:const allowedOrigins = [ 'http://localhost:8000', // 本地前端地址 'https://your-frontend-vercel-domain.vercel.app' // 生产前端域名 ]; app.use(cors({ credentials: true, origin: (origin, callback) => { if (!origin || allowedOrigins.includes(origin)) { callback(null, true); } else { callback(new Error('Not allowed by CORS')); } } }));修正Cookie设置属性:
在后端登录接口设置Cookie时,添加适配生产环境的属性:// 示例:登录接口中设置Cookie的代码 res.cookie('token', token, { httpOnly: true, secure: process.env.NODE_ENV === 'production', // 生产环境强制HTTPS传输 sameSite: process.env.NODE_ENV === 'production' ? 'None' : 'Lax', maxAge: 3 * 24 * 60 * 60 * 1000 // 有效期3天 });清理前端冗余请求头:
删除请求中的Access-Control-Allow-Credentials字段:const getProfilePic = async ()=>{ try { const response = await fetch('https://blog-app-server-red.vercel.app/user/'+userId , { credentials : 'include', headers: { "Content-Type": "application/json" } })
内容的提问来源于stack exchange,提问作者Aditya Nagare
相关产品推荐
相关产品推荐

