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

部署到Vercel的MERN应用JWT Token未存入Cookie问题求助

MERN应用部署Vercel后JWT Cookie不存储及验证失败问题

使用MERN(React+Express+MongoDB)栈开发的应用本地运行完全正常,但部署到Vercel后出现以下问题:

  • JWT Token已正常生成,且能在响应头的Set-Cookie字段中看到,但浏览器的Cookie存储中无该Cookie(开发者工具中无法找到)
  • 后续请求的JWT验证流程失败,返回未授权错误

报错截图

Vercel响应头截图

Vercel响应头截图

开发者工具报错截图

开发者工具报错1
开发者工具报错2


相关代码

index.js

const dotenv = require("dotenv");
const mongoose = require("mongoose");
const express = require("express");
const cors = require("cors");
const cookieParser = require("cookie-parser");
const jwt = require("jsonwebtoken");
const app = express();
//const configs = require("./config.js");

dotenv.config({ path: "./config.env" });
require("./db/connection");
//const config = configs[process.env.NODE_ENV || "development"];

app.use(express.json());
app.use(cookieParser());

// 使用CORS中间件允许特定来源的请求
app.use(
    cors({
        origin: "https://frontEnd.vercel.app", // 替换为你的前端URL
        methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
        credentials: true, // 允许请求携带Cookie和凭证
    })
);

app.use(require("./router/route"));

// 空中间件
const middleware = (req, res, next) => {
    next();
};
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
    console.log(`服务运行在端口 ${PORT}`);
});

route.js

const express = require("express");
const bcrypt = require("bcrypt");

const router = express.Router();

require("../db/connection");
const User = require("../model/newUserSchema");
const Auth = require("../middleware/auth");

router.get("/", (req, res) => {
    res.send("后端服务已启动");
});

// 注册模块
router.post("/signup", async (req, res) => {
    const { username, email, cpassword, retypePassword } = req.body;

    if (!username || !email || !cpassword || !retypePassword) {
        return res.status(422).json({ error: "请填写完整信息" });
    }

    try {
        const UserExist = await User.findOne({ email: email });

        if (UserExist) {
            return res.status(422).json({ error: "该邮箱已注册" });
        } else if (cpassword !== retypePassword) {
            return res.status(422).json({ error: "两次输入的密码不一致" });
        } else {
            const user = new User({
                username,
                email,
                cpassword,
                retypePassword,
            });

            const userResgister = await user.save();

            if (userResgister) {
                return res.status(201).json({ message: "注册成功" });
            }
        }
    } catch (error) {
        console.log(error);
    }
});

// 登录模块
router.post("/signin", async (req, res) => {
    try {
        const { email, cpassword } = req.body;

        if (!email || !cpassword) {
            return res.status(400).json({ error: "请输入完整登录凭证" });
        }

        const userLogin = await User.findOne({ email: email });

        if (userLogin) {
            const isMatch = await bcrypt.compare(cpassword, userLogin.cpassword);

            const token = await userLogin.generateAuthToken();
            console.log("JWT Token: ", token);
            // 设置Cookie并指定正确的域名和路径(已注释)
            // res.cookie("signinToken", token, {
            //     domain: "https://backend-api.vercel.app", // 设置域名以匹配前后端
            //     path: "/signin", // 设置Cookie生效路径为登录接口
            //     expires: new Date(Date.now() + 25892000000),
            //     httpOnly: true,
            // });

            res.cookie("signinToken", token, {
                expires: new Date(Date.now() + 25892000000),
                httpOnly: true,
            });

            if (isMatch) {
                return res.status(200).json({ message: "登录成功" });
            } else {
                return res.status(400).json({ error: "登录凭证无效" });
            }
        } else {
            return res.status(400).json({ error: "登录凭证无效" });
        }
    } catch (error) {
        console.log(error);
    }
});

// 收藏列表模块(需JWT验证用户身份)
router.get("/watchlist", Auth, (req, res) => {
    res.send(req.rootuser);
});

// 退出登录模块
router.get("/signout", (req, res) => {
    res.clearCookie("signinToken", { path: "/" });
    res.status(200).send("退出登录成功");
});

module.exports = router;

Auth.js(JWT验证中间件)

const jwt = require("jsonwebtoken");
const User = require("../model/newUserSchema");

const SECRETKEY = "myScretKeyyyyyyyyyyyyeeee";

const Auth = async (req, res, next) => {
    try {
        const token = req.cookies.signinToken;
        if (!token) {
            console.log("未找到Token");
            return res.sendStatus(403);
        }
        const verifytoken = jwt.verify(token, SECRETKEY);

        const rootuser = await User.findOne({ _id: verifytoken._id, "tokens.token": token });

        if (!rootuser) {
            throw new Error("用户不存在");
        }

        req.token = token;
        req.rootuser = rootuser;
        req.UserID = rootuser._id;

        next();
    } catch (error) {
        res.status(401).send("未授权访问:未找到有效Token");
        console.log(error);
    }
};

module.exports = Auth;

内容的提问来源于stack exchange,提问作者Tapesh Patel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:34:55