node.js - 为什么我重新启动服务器后,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
}));
解决方案
如果我的回答有用,请添加投票:D
我遇到了和你一样的问题。我花了 3-4 个小时来解决这个问题。
我不知道为什么,但是很多教程将序列化和反序列化添加到 Local-Strategy - 这是错误的! 序列化和反序列化属于护照实例,因此我们可以在本地策略之前或之后进行。记得express-session
在之后和之前添加所有护照配置(本地策略,序列化和反序列化)passport.initialize() & passport.session()
。
Error: failed to deserialize user out of session
- 登录有效,因为您启动了本地策略,您已经实现了序列化和反序列化并且服务器知道他们必须做什么。当您在 FrontEnd 从 cookie 中检查活动会话时,您没有启动本地策略并且服务器不知道反序列化是什么。
代码
- 文件:'./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());
- 文件:'./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。前端 - 反应,后端 - 表达。
推荐阅读
- java - 可运行的 JAR 未检测到 logback.xml 配置
- pdf - iText 的 SameLine 函数背后的逻辑是什么?
- python - 在反向关系列表中过滤 Django 模型
- javascript - 希望在按下提交输入时显示文本,并在 3 秒后重定向到 Index.html
- entity-framework - 无法“预热”实体框架
- react-native - 在 react-native-gifted-chat 中编辑头像位置
- javascript - 如何检查表的值是否串联?
- javascript - 全屏html5中的关闭按钮
- bash - CPP 检查不在本地机器上
- javascript - 如何使用 DoCheck [Angular] 在月份选择器上反映/突出显示手动输入的月份