You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MERN项目本地Cookie正常,Vercel部署后refresh token无法获取求助

MERN项目部署Vercel后Cookie无法正常获取问题排查

问题现象

  • 登录控制器可正常生成refresh token并执行Cookie设置操作,但浏览器开发者工具「Application → Cookies」中无法看到该Cookie;
  • 页面刷新时,generateAccessToken控制器无法读取到refresh token,接口返回提示“Connectez-vous SVP.”(请登录)。

相关代码

登录控制器代码

login: async (req, res) => {
    try {
        const { email, password } = req.body

        const user = await Users.findOne({email})
        .populate("followers following", "avatar username fullname followers following")

        if(!user) return res.status(400).json({msg: "Cette Email n'existe pas."})

        const isMatch = await bcrypt.compare(password, user.password)
        if(!isMatch) return res.status(400).json({msg: "Mot de passe incorrecte."})

        const access_token = createAccessToken({id: user._id})
        const refresh_token = createRefreshToken({id: user._id})

        res.cookie('refreshtoken', refresh_token, {
            httpOnly: true,
            path: '/api/refresh_token',
            maxAge: 30*24*60*60*1000 // 30days
        })

        res.json({
            msg: 'Connexion terminée!',
            access_token,
            user: {
                ...user._doc,
                password: ''
            }
        })
    } catch (err) {
        return res.status(500).json({msg: err.message})
    }
},

GenerateAccessToken控制器代码

generateAccessToken: async (req, res) => {
    try {
        const rf_token = req.cookies.refreshtoken
        if(!rf_token) return res.status(400).json({msg: "Connectez-vous SVP."})

        jwt.verify(rf_token, process.env.REFRESH_TOKEN_SECRET, async(err, result) => {
            if(err) return res.status(400).json({msg: "Connectez-vous SVP."})

            const user = await Users.findById(result.id).select("-password")
            .populate('followers following', 'avatar username fullname followers following')

            if(!user) return res.status(400).json({msg: "Utilisateur n'existe pas."})

            const access_token = createAccessToken({id: result.id})

            res.json({
                access_token,
                user
            })
        })
        
    } catch (err) {
        return res.status(500).json({msg: err.message})
    }
}

问题原因及解决方案

本地正常但Vercel部署后异常,核心是跨域环境下的Cookie规则差异,以下是具体排查点和修复方案:

1. 缺失SameSite与Secure属性

Vercel部署后前后端通常为跨域场景,浏览器默认的Cookie SameSite规则会限制跨域Cookie的存储。需补充以下Cookie配置:

  • sameSite: 'none':允许跨域携带Cookie,必须配合secure: true(浏览器要求SameSite=None的Cookie必须是HTTPS传输)
  • secure: true:仅在HTTPS环境下发送Cookie,Vercel默认是HTTPS,必须开启

修改登录控制器中的Cookie设置:

res.cookie('refreshtoken', refresh_token, {
    httpOnly: true,
    path: '/api/refresh_token',
    maxAge: 30*24*60*60*1000, // 30days
    secure: process.env.NODE_ENV === 'production', // 仅生产环境开启
    sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax' // 生产环境设为none
})

2. CORS配置未允许凭证传递

如果前后端域名不同,后端CORS必须明确允许携带凭证,同时前端请求也要开启withCredentials: true:

  • 后端Express配置CORS:
const cors = require('cors');
app.use(cors({
    origin: process.env.CLIENT_URL, // 替换为你的前端Vercel域名,如https://your-frontend.vercel.app
    credentials: true // 允许携带Cookie等凭证
}));
  • 前端请求(以Axios为例):
axios.post('/api/login', data, { withCredentials: true })
axios.get('/api/refresh_token', { withCredentials: true })

3. Cookie路径与接口路径不匹配

检查path: '/api/refresh_token'是否与generateAccessToken接口的实际路径完全一致。如果接口路径是/api/refresh-token或其他,Cookie将无法被携带到该接口,需调整路径匹配。

4. Vercel环境变量配置

确保Vercel后台已正确配置REFRESH_TOKEN_SECRET等环境变量,避免因变量缺失导致JWT验证失败(虽然这不会直接导致Cookie不显示,但可能引发后续Token验证错误)。


内容的提问来源于stack exchange,提问作者Yanis Saadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 04:12:02