NodeJS 多个用户的同一会话

问题描述 投票:0回答:1

我尝试为每个用户提供不同的会话,这最初是有效的。但是,一旦第二个用户登录,它就会覆盖第一个会话并将其分配给两个用户。正如预期的那样,在注销任一用户后,另一个用户会输出错误并且不再能够访问会话数据。我尝试查找代码中的错误,但无法找出会话在哪里被共享或覆盖。我也尝试过谷歌搜索但无济于事。我认为我在这里遗漏了一些明显的东西。

这是我的 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
    });
}
javascript node.js express session pug
1个回答
0
投票

很抱歉,但我无法查看您的代码,如果您想为每个用户拥有不同的会话,您应该进行自己的会话身份验证

首先制作猫鼬模型

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();
};

我希望我能够帮助您,每次登录都会为用户创建一个新会话,并且您可以同时为多个用户为同一用户创建多个会话

© www.soinside.com 2019 - 2024. All rights reserved.