Express中req.session.userId参数丢失问题求助
会话无法保留userId参数的问题排查与修复
问题描述
在/login路由中设置req.session.userId后,控制台打印显示该参数已存在于req.session中,但访问/check-auth路由时,无法获取到包含userId的会话数据,导致无法通过会话判断用户登录状态。
问题根源与修复方案
1. MongoDB连接字符串语法错误
原代码中mongoose的连接字符串末尾多了一个],这会导致数据库连接异常,进而影响会话的持久化存储。
修复:
// 移除末尾多余的] const mongoDB = "mongodb://127.0.0.1:27017/project";
2. 未定义server变量导致退出时报错
process.on('SIGINT')中调用server.close(),但server变量未通过app.listen()的返回值定义,会导致进程退出时无法正确关闭服务器,可能影响会话数据的保存。
修复:
// 将app.listen的返回值赋值给server const server = app.listen(port, () => { console.log(`Example app listening on port ${port}`); });
3. 会话保存时机问题
直接在设置req.session.userId后发送响应,可能会因为会话异步保存未完成,导致数据未写入MongoDB。
修复:
在req.session.save()的回调中再发送响应,确保会话数据持久化完成:
app.post("/login", async (req, res) => { try { let { username, password } = req.body; let user = await users.findOne({ username: username }); if (user && (await bcrypt.compare(password, user.passwordHash))) { req.session.userId = user._id; // 等待会话保存完成后返回响应 req.session.save((err) => { if (err) { console.error("Session save error:", err); return res.status(500).json("Internal server error"); } console.log("Session:", req.session); res.status(200).send("Login successful!"); }); } else { res.status(401).json({ error: "Invalid credentials" }); } } catch (error) { console.error("Internal server error", error.message); res.status(500).json("Internal server error"); } });
4. 前端请求未携带凭证
如果前端未配置携带会话凭证,浏览器不会自动发送会话Cookie,后端自然无法识别用户会话。
前端配置示例:
- Axios:
axios.get('http://localhost:8000/check-auth', { withCredentials: true })
- Fetch:
fetch('http://localhost:8000/check-auth', { credentials: 'include' })
5. 可选:调整Cookie的domain配置
部分浏览器对localhost域名的Cookie处理存在差异,可尝试注释掉domain配置,让Express自动适配:
cookie: { maxAge: 24 * 60 * 60 * 1000, // domain: "localhost", // 注释掉该配置 secure: false, httpOnly: true, }
修复后的完整代码
const express = require("express"); const session = require("express-session"); const MongoStore = require("connect-mongo"); const mongoose = require("mongoose"); const bcrypt = require("bcrypt"); const cors = require("cors"); const users = require("./models/user"); const app = express(); const port = 8000; const saltRounds = 10; // 修正MongoDB连接字符串 const mongoDB = "mongodb://127.0.0.1:27017/project"; mongoose .connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true }) .then(() => console.log("Connected to database")) .catch((error) => console.error("Error connecting to database:", error)); const db = mongoose.connection; db.on("error", console.error.bind(console, "MongoDB connection error:")); db.on("connected", function () { console.log("Connected to database"); }); app.use( session({ secret: "Super secret secret", cookie: { maxAge: 24 * 60 * 60 * 1000, // domain: "localhost", // 可选:注释掉适配部分浏览器 secure: false, httpOnly: true, }, resave: false, saveUninitialized: false, store: MongoStore.create({ mongoUrl: "mongodb://127.0.0.1:27017/project", }), }) ); app.use( cors({ origin: "http://localhost:3000", methods: ["POST", "PUT", "GET", "OPTIONS", "HEAD"], credentials: true, }) ); app.use(express.json()); // 定义server变量 const server = app.listen(port, () => { console.log(`Example app listening on port ${port}`); }); process.on("SIGINT", () => { console.log("Server closed. Database instance disconnected"); server.close(() => { db.close(() => { process.exit(0); }); }); }); app.post("/login", async (req, res) => { try { let { username, password } = req.body; let user = await users.findOne({ username: username }); if (user && (await bcrypt.compare(password, user.passwordHash))) { req.session.userId = user._id; // 等待会话保存完成后响应 req.session.save((err) => { if (err) { console.error("Session save error:", err); return res.status(500).json("Internal server error"); } console.log("Session:", req.session); res.status(200).send("Login successful!"); }); } else { res.status(401).json({ error: "Invalid credentials" }); } } catch (error) { console.error("Internal server error", error.message); res.status(500).json("Internal server error"); } }); app.get("/check-auth", async (req, res) => { try { console.log("Session in check-auth:", req.session); console.log("Session User:", req.session.userId); if (req.session && req.session.userId) { let user = await users.findById(req.session.userId); console.log("User Details:", user); if (user) { res.status(200).json({ authenticated: true, user }); } else { res.status(401).json({ authenticated: false }); } } else { res.status(200).json({ authenticated: false }); } } catch (error) { console.error("Error checking authentication: ", error); res.status(500).json({ authenticated: false, error: "Internal server error", }); } });
内容的提问来源于stack exchange,提问作者Zarif Ahmed
相关产品推荐
相关产品推荐

