我尝试为每个用户提供不同的会话,这最初是有效的。但是,一旦第二个用户登录,它就会覆盖第一个会话并将其分配给两个用户。正如预期的那样,在注销任一用户后,另一个用户会输出错误并且不再能够访问会话数据。我尝试查找代码中的错误,但无法找出会话在哪里被共享或覆盖。我也尝试过谷歌搜索但无济于事。我认为我在这里遗漏了一些明显的东西。
这是我的 app.js 的相关部分
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const session = require("express-session");
const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
var mongoose = require("mongoose");
const cors = require('cors');
const Schema = mongoose.Schema;
const asyncHandler = require("express-async-handler");
const { body, validationResult } = require("express-validator");
const flash = require('express-flash');
const bcrypt =require("bcryptjs");
const dotenv = require('dotenv').config();
const dotenv2 = require('dotenv');
const User = require("./models/user");
const MessageList = require("./models/messageList");
const Message = require("./models/message");
//const axios = require("axios");
var indexRouter = require('./routes/routes');
let x = JSON.parse(process.env.SESSION);
const mongoDb = process.env.MONGODB_URL;
/*mongoose.set("strictQuery", false);
main().catch((err) => console.log(err));
async function main() {
await mongoose.connect(mongoDB);
}
*/
mongoose.connect(mongoDb, { useUnifiedTopology: true, useNewUrlParser: true });
const db = mongoose.connection;
db.on("error", console.error.bind(console, "mongo connection error"));
/*const User = mongoose.model(
"user",
new Schema({
username: { type: String, required: true },
password: { type: String, required: true }
})
);*/
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(express.static('css'));
app.use(logger('dev'));
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
//app.use(express.static(path.join(__dirname, "messenger", "build")));
app.use(express.static(path.join(__dirname, 'public', 'stylesheets')));
app.use(express.static(path.join(__dirname, 'public', 'images')));
passport.use(
new LocalStrategy(async(username, password, done) => {
try {
const user = await User.findOne({ username: username });
if (!user) {
return done(null, false, { message: "Incorrect username" });
};
bcrypt.compare(password, user.password, (err, res) => {
if (res) {
// passwords match! log user in
return done(null, user)
} else {
// passwords do not match!
return done(null, false, { message: "Incorrect password" })
}
})
} catch(err) {
console.log("uh-oh");
return done(err);
};
})
);
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(async function(id, done) {
try {
const user = await User.findById(id);
done(null, user);
} catch(err) {
done(err);
};
});
app.use(function(req, res, next) {
res.locals.currentUser = req.user;
next();
});
app.use(flash());
//app.use(session({ secret: "cats", resave: false, saveUninitialized: false }));
app.use(express.urlencoded({ extended: false }));
app.use(session(x));
app.use(passport.initialize());
app.use(passport.session());
app.use('/', indexRouter);
app.get("/", (req, res) => {
//console.log(req.user);
res.render("login");
});
app.post("/",
passport.authenticate("local", {
successRedirect: "/homepage",
failureRedirect: "/",
failureFlash:true
})
);
这是加载页面的函数:
exports.homepage = async(req,res,next) => {
const users = await User.find().populate("lastReceiver").sort({id:1}).exec();
await req.user.populate("lastReceiver");
const lastReceiver = req.user.lastReceiver;
//var currentReceiver = await req.user.currentReceiver;
//console.log("Initial Load: " + req.user.currentReceiver)
// do an if statement: dont set to null when tmpUser currently has a value
/*if(currentReceiver == undefined) {
currentReceiver = null;
}
*/
console.log(req.session);
console.log(req.user);
//console.log("lastReceiver: " + lastReceiver);
res.render("homepage", {
users:users,
user:req.user,
lastReceiver:lastReceiver,
//tmpUser:currentReceiver
});
}
很抱歉,但我无法查看您的代码,如果您想为每个用户拥有不同的会话,您应该进行自己的会话身份验证
首先制作猫鼬模型
const mongoose = require("mongoose");
const session = new mongoose.Schema({
sessionId: String,
createdAt: Date,
userId: { ref: "user", type: mongoose.Types.ObjectId },
});
module.exports = mongoose.model("session", session);
用户登录时第二个处理会话创建
//after user authentication
const session = new Session();
const time = new Date().valueOf().toString();
session.sessionId =
crypto.randomBytes(64).toString("hex") +
crypto.createHash("sha256").digest(time).toString("hex");
session.createdAt = new Date();
session.userId = user._id;
await session.save();
user.sessions.push(session._id);
await user.save();
第三次处理cookies
//if you want to have mutiple sessions on the same device
res.cookie(
session._id.toString(),
JSON.stringify({session,name:u.name,_id:u._id}), { maxAge: 60000 * 15
});
//if you want to have one session per device
res.cookie(
"session",
JSON.stringify({session,name:u.name,_id:u._id}), { maxAge: 60000 * 15
});
现在,如果您想检查某个请求(例如主页请求)的会话,您可以这样做
const { ObjectId } = require('mongoose').Types;
const authenticateUser = async (req, res, next) => {
let sessionId, cookie, data;
//this approach is for multipal sessions on the same device you have to
//send along the session id for the cookie
sessionId = req.body.session_id;
try {
cookie = JSON.parse(req.cookies[sessionId]);
} catch (err) {
console.error(err,'req.body', req.body, sessionId);
return res.end();
}
const authSession = await Session.findOne({
_id: new ObjectId(sessionId),
sessionId: cookie.session.sessionId,
userId: new ObjectId(cookie._id),
});
if (!authSession) {
return res.end();
}
const user = await User.findOne({
_id: authSession.userId,
});
//here you can set a timelimit for sessions but for this you also need
//logic to refresh sessions
const isSessionValid =
15 > (new Date().valueOf() - authSession.createdAt.valueOf()) / 60000;
if (!isSessionValid) {
return res.end();
}
req.user = user;
req.session = authSession;
next();
};
我希望我能够帮助您,每次登录都会为用户创建一个新会话,并且您可以同时为多个用户为同一用户创建多个会话