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

Node服务器会话创建异常:认证与Cookie问题排查求助

问题分析与解决方案

现存问题

  • 需要身份验证的路由无需登录或携带Cookie即可访问
  • 登录后Cookie已设置,但登出后Cookie仍未清除

调试日志信息

1. 未设置Cookie时访问localhost:3000/

express-session no SID sent, generating session +0ms

2. 使用有效凭证请求localhost:3000/login/password

express-session no SID sent, generating session +0ms
express-session no SID sent, generating session +3m
express-session set-cookie connect.sid=s%3AuQgx27XnqODttfCECNGsaeJLOWZhk04e.qnHVj9HmUs2svxtb4mb6R9xpw3imbf0kUEhOiRlNXr4; Path=/; HttpOnly +105ms
express-session split response +9ms
express-session fetching uQgx27XnqODttfCECNGsaeJLOWZhk04e +439ms
express-session session found +8ms
express-session touching +5ms
express-session split response +2ms
express-session touched +10ms

3. 请求localhost:3000/logout

express-session fetching uQgx27XnqODttfCECNGsaeJLOWZhk04e +2m
express-session session found +4ms
express-session saving uQgx27XnqODttfCECNGsaeJLOWZhk04e +18ms
express-session set-cookie connect.sid=s%3ADEXRlWTn14GqFZU06YdLC-bemM8rn_ri.1v71XtDmg88F5brCD5yy3BsLvQ1UuGv%2FYS3vTeWD%2FUk; Path=/; HttpOnly +40ms
express-session split response +6ms
express-session fetching DEXRlWTn14GqFZU06YdLC-bemM8rn_ri +144ms
express-session session found +1ms
express-session touching +1ms
express-session split response +1ms
express-session touched +2ms

问题根源与修复方案

1. 路由未做身份验证拦截

你的代码里没有对需要保护的路由(比如/)添加身份验证校验逻辑,导致任何人都能直接访问。需要新增一个自定义中间件来检查用户是否已登录:

// 身份验证中间件
function ensureAuthenticated(req, res, next) {
  if (req.isAuthenticated()) {
    return next();
  }
  res.redirect('/login'); // 未登录则跳转到登录页
}

将这个中间件应用到需要保护的路由上:

app.get("/", ensureAuthenticated, (req, res) => {
  res.json({
    name: "Sourabh Roy",
    class: 9,
    section: "A",
    roll: 27,
    pass: "PASSED",
  });
});

2. 登出时未清除Cookie

默认的req.logout()只会销毁服务器端的会话数据,但不会主动清除客户端的Cookie。需要在登出逻辑中手动设置Cookie过期:
修改登出路由代码:

app.post("/logout", function (req, res, next) {
  req.logout(function (err) {
    if (err) {
      return next(err);
    }
    // 清除connect.sid会话Cookie
    res.clearCookie('connect.sid');
    res.redirect("/");
  });
});

额外说明

  • 日志中no SID sent是首次请求时客户端未携带会话Cookie,服务器生成新会话的正常现象;
  • 登出时出现新的connect.sid是req.logout()默认会重新生成会话ID,添加clearCookie后客户端将不再携带旧Cookie;
  • 当前验证逻辑(username == 1 && password == 1)仅适合测试,实际项目需从数据库查询用户并使用加密算法(如bcrypt)验证密码。

完整修复代码

const express = require("express");
const app = express();
const doten = require("dotenv");
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));
const courses = [
  { name: "aa", class: 5 },
  { name: "bb", class: 7 },
  { name: "cc", class: 8 },
  { name: "dd", class: 4 },
];
const user = [{}];
var passport = require("passport");
var LocalStrategy = require("passport-local");
var session = require("express-session");

passport.use(
  new LocalStrategy(function verify(username, password, cb) {
    if (username == 1 && password == 1) return cb(null, username);
    else return cb(null, false, { message: "Incorrect username or password." });
  })
);

app.use(
  session({
    secret: "keyboard cat",
    resave: false,
    saveUninitialized: false,
    cookie: { secure: false },
  })
);

app.use(passport.authenticate("session"));
passport.serializeUser(function (username, cb) {
  process.nextTick(function () {
    return cb(null, {
      username: username,
    });
  });
});

passport.deserializeUser(function (user, cb) {
  process.nextTick(function () {
    return cb(null, user);
  });
});

// 身份验证中间件
function ensureAuthenticated(req, res, next) {
  if (req.isAuthenticated()) {
    return next();
  }
  res.redirect('/login');
}

app.post(
  "/login/password",
  passport.authenticate("local", {
    successRedirect: "/",
    failureRedirect: "/login",
  })
);

app.get("/", ensureAuthenticated, (req, res) => {
  res.json({
    name: "Sourabh Roy",
    class: 9,
    section: "A",
    roll: 27,
    pass: "PASSED",
  });
});
app.get("/books/:name", (req, res) => {
  res.send({ ...req.params, ...req.query });
});

app.post("/signup", (req, res) => {
  let temp_user = req.body;
  console.log(req.body);
  user.push(temp_user);
  res.send(req.body);
});

app.post("/logout", function (req, res, next) {
  req.logout(function (err) {
    if (err) {
      return next(err);
    }
    res.clearCookie('connect.sid');
    res.redirect("/");
  });
});

app.listen(3000, (err) => {
  if (err) console.log("hi");
  else console.log("Server is up at port 3000");
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:47:04