首页 > 解决方案 > 为什么我重新启动服务器后,passport.js 不能反序列化用户?

问题描述

问题我正在使用 passport.js 来验证我的用户。一切正常,他们可以登录。他们的 id 被序列化到会话中,并且在后续请求中访问 req.user 时也会被反序列化。但是当我关闭服务器或重新启动并转到任何路线时。它给了我一个错误,“无法反序列化用户退出会话”。我注意到当我从我的数据库中删除用户会话时(我正在使用云托管的 mongo-db),我必须再次登录并且它工作正常,直到我再次重新启动我的服务器(这在开发中很常见)。我无法删除会话,一次又一次,然后再次登录。这是一个巨大的麻烦。有谁知道可能导致这种情况的原因?

编辑 这是我使用的代码:

passport.js 策略文件

const passport = require('passport');
const User = require('./../models/user.js');
const bcrypt = require('bcrypt');

const LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy({usernameField : 'email'}, (email, password, done) => {
  //see if the user with such username exists
  User.findOne({email}, (err, user) => {
    if (err) {
      return done(err, false, {message : "Something went wrong."});
    }

    if(!user) {
      return done(null, false, {message : "No such user exists."});
    }

    //check if the password matches
    bcrypt.compare(password , user.password).then(match => {
      if(!match) {
        return done(null, false, {message : "Password and email doesn't match."});
      }
      done(null, user, {message : "Log in successful"});
    }).catch(err => {
      done(err, false, {message : "Something went wrong. Try again."});
    });

    passport.serializeUser((user, done) => {
      done(null, user._id, );
    });

    passport.deserializeUser((id, done) => {
      User.findById(id, (err, user) => {
        done(err, user);
      })
    });
  });
})
);

会话配置:

app.use(session({
  secret : process.env.COOKIE_SECRET,
  name : "PizzaCartSession",
  resave : false,
  store : mongoStore,
  saveUninitialized : false,
  cookie : {maxAge : 1000 * 60 * 60,} // 4 hours
}));

标签: node.jsexpresspassport.js

解决方案


如果我的回答有用,请添加投票:D
我遇到了和你一样的问题。我花了 3-4 个小时来解决这个问题。
我不知道为什么,但是很多教程将序列化和反序列化添加到 Local-Strategy - 这是错误的! 序列化和反序列化属于护照实例,因此我们可以在本地策略之前或之后进行。记得express-session在之后和之前添加所有护照配置(本地策略,序列化和反序列化)passport.initialize() & passport.session()

Error: failed to deserialize user out of session- 登录有效,因为您启动了本地策略,您已经实现了序列化和反序列化并且服务器知道他们必须做什么。当您在 FrontEnd 从 cookie 中检查活动会话时,您没有启动本地策略并且服务器不知道反序列化是什么。

代码

  1. 文件:'./server.js'
// Express Session
app.use(
  session({
    secret: process.env.secret,
    saveUninitialized: true,
    resave: false,
    // Default store is only for debug - Save session in MongoDB
    store: new MongoStore({
      mongooseConnection: mongoose.connection,
      collection: 'sessions',
    }),
    cookie: {
      maxAge: 1000 * 60 * 60 * 24, // one day
    },
  })
);

// Added & Init Passport Local Config for entire App
require('./config/passportConfig')(passport);
// Init passport & session
app.use(passport.initialize());
app.use(passport.session());
  1. 文件:'./config/passportConfig'
const User = require('../models/User');
const LocalStrategy = require('passport-local').Strategy;

// Why we pass instances of passport to functions when we call it  ??
// Bc we want the same instane of passort in our entire appliaction
module.exports = (passport) => {
//----------Start Local-Strategy----------//
  passport.use(
    new LocalStrategy(
      { usernameField: 'email' }, // we show that we have an email field like username
      async (email, password, done) => {
        try {
          // 1. Looking for User & his paassword in DB by email
          const user = await User.findOne({ email }).select('+password');
          // 2. Checking if user exists
          if (!user) {
            return done(null, false, {
              // If not exist stop function and return msg to login control
              msg: 'That email is not registered',
            });
          }
          // 3. Comparing password from form with password from DB
          // Using method from UserSchema
          const isMatch = await user.matchPassword(password);
          if (isMatch) {
            // If is match stop function adn return user to login control
            return done(null, user, { msg: 'User Found' });
          } else {
            // If not exist stop function and return msg to login control
            return done(null, false, { msg: 'Incorrect Password' });
          }
        } catch (error) {
          // If error with connection with DB return msg  to login control
          console.error(error);
          return done(null, false, { msg: 'Server Error' });
        }
      }
    )
  );
//----------End of Local-Strategy----------//
  // Serialize only user id
  passport.serializeUser(function (user, done) {
    done(null, user.id);
  });
  // Deserialize by user id
  passport.deserializeUser((id, done) => {
    User.findById(id)
      .then((user) => {
        done(null, user);
      })
      .catch((err) => done(err));
  });
};

如果您想要更多代码,请查看我的 repo。前端 - 反应,后端 - 表达。


推荐阅读