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

Node.js后端登出时Cookie返回Undefined问题求助

NodeJS 登录/登出接口问题:登出时服务器无法识别Cookie

我正在学习NodeJS,开发登录与登出接口。登录接口能正常返回预期结果并设置Cookie,但登出接口存在问题:服务器端无法识别Cookie,打印结果为undefined。

Cookie设置成功截图

后端登录代码

const bcrypt = require("bcrypt");
const users = {
  users: require("../model/users.json"), // 通常从外部数据库获取数据
  setUsers: function (data) {
    this.users = data;
  },
};
const jwt = require("jsonwebtoken");
require("dotenv").config();
const fsPromises = require("fs").promises;
const path = require("path");

const login = async (req, res) => {
  const { username, password } = req.body;
  if (!username || !password) {
    return res
      .status(400)
      .json({ success: false, message: "用户名和密码为必填项" });
  }
  const userFound = users.users.find((user) => user.username === username);
  if (!userFound) {
    return res.status(400).json({ success: false, message: "用户不存在" });
  }

  const isPasswordMatch = await bcrypt.compare(password, userFound.password);
  if (!isPasswordMatch) {
    return res
      .status(401)
      .json({ success: false, message: "密码无效" });
  }
  const accessToken = jwt.sign(
    { username: username },
    process.env.ACCESS_TOKEN_SECRET,
    {
      expiresIn: "1d",
    }
  );
  const refreshToken = jwt.sign(
    { username },
    process.env.REFRESH_TOKEN_SECRET,
    {
      expiresIn: "1w",
    }
  );
  // 修复:此处应该用username而非userName
  const otherUsers = users.users.filter(
    (user) => user.username != userFound.username
  );
  const currentUser = { ...userFound, refreshToken };
  users.setUsers([...otherUsers, currentUser]);

  await fsPromises.writeFile(
    path.join(__dirname, "../model", "users.json"),
    JSON.stringify(users.users, null, 1),
    "utf-8"
  );

  res.cookie("jwt", refreshToken, {
    httpOnly: true,
    maxAge: 24 * 60 * 60 * 1000, // 24小时(毫秒)
    sameSite: "None",
    // secure: true, // 生产环境下HTTPS时启用
  });

  return res.status(200).json({ success: true, message: accessToken });
};
module.exports = { login };

后端登出代码

const users = {
  users: require("../model/users.json"), // 通常从外部数据库获取数据
  setUsers: function (data) {
    this.users = data;
  },
};
const fsPromises = require("fs").promises;
const path = require("path");

const logout = async (req, res) => {
  const cookies = req.cookies;
  console.log(cookies);
  if (!cookies?.jwt) {
    return res.sendStatus(204); // 请求成功但无内容返回
  }
  const refreshToken = cookies.jwt;
  // 检查refreshToken是否存在于用户数据中
  const UserFound = users.users.find(
    (user) => user.refreshToken === refreshToken
  );
  if (!UserFound) {
    // 修复:sameSite属性大小写统一为None
    res.clearCookie("jwt", {
      httpOnly: true,
      sameSite: "None",
      // secure: true,
    });
    return res
      .status(204)
      .json({ success: true, message: "成功登出" });
  }
  // 修复:此处应该用username而非userName
  const otherUsers = users.users.filter(
    (user) => user.username != UserFound.username
  );
  const currentUser = { ...UserFound, refreshToken: "" };
  users.setUsers([...otherUsers, currentUser]);
  await fsPromises.writeFile(
    path.join(__dirname, "../model", "users.json"),
    JSON.stringify(users.users, null, 1),
    "utf-8"
  );
  res.clearCookie("jwt", {
    httpOnly: true,
    sameSite: "None",
    // secure: true,
  }); // 生产环境下HTTPS时添加secure:true
  return res
    .status(204)
    .json({ success: true, message: "成功登出" }); // 请求成功但无内容返回
};
module.exports = { logout };

问题排查与解决方案

  1. 添加Cookie解析中间件
    Express默认不解析Cookie,必须安装并配置cookie-parser:

    npm install cookie-parser
    

    在Express主文件中引入并使用:

    const cookieParser = require('cookie-parser');
    app.use(cookieParser());
    
  2. 处理跨域Cookie传递
    如果前后端跨域,需要:

    • 前端请求时设置withCredentials: true(以Axios为例:axios.post('/logout', {}, { withCredentials: true }))
    • 后端配置CORS允许凭证:
      const cors = require('cors');
      app.use(cors({
        origin: 'http://localhost:3000', // 替换为你的前端域名
        credentials: true
      }));
      
  3. 统一Cookie属性大小写
    登出时清除Cookie的sameSite属性要和登录时一致,均为"None"(原登出代码中有一处写为"none",大小写不匹配会导致Cookie操作失效)。

  4. 修复用户数据筛选错误
    登录和登出代码中筛选用户时误用了userName,实际用户对象属性是username,该错误会导致refreshToken无法正确更新到用户数据中,需修正。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:44:54