Javascript 使用异步身份验证路由和passport.js时未序列化用户
我有一个单独运行的节点应用程序。如果客户端中没有js,它只是同步运行,使用passport.js设置cookie。当客户端启用js时,则通过rest路由完成身份验证 一切似乎都很好,除了如果我已经通过身份验证并异步设置了Cookie,但随后刷新页面或同步导航到新页面(无论出于何种原因),服务器会使用新的Cookie发送响应,覆盖旧的Cookie,并将用户设置回未经身份验证的状态Javascript 使用异步身份验证路由和passport.js时未序列化用户,javascript,node.js,cookies,asynchronous,express,Javascript,Node.js,Cookies,Asynchronous,Express,我有一个单独运行的节点应用程序。如果客户端中没有js,它只是同步运行,使用passport.js设置cookie。当客户端启用js时,则通过rest路由完成身份验证 一切似乎都很好,除了如果我已经通过身份验证并异步设置了Cookie,但随后刷新页面或同步导航到新页面(无论出于何种原因),服务器会使用新的Cookie发送响应,覆盖旧的Cookie,并将用户设置回未经身份验证的状态 // ====================================================
// =============================================================================
// AUTHENTICATE (FIRST LOGIN) ==================================================
// =============================================================================
// process the login form
app.post('/login', passport.authenticate('local-login', {
successRedirect: '/profile', // redirect to the secure profile section
failureRedirect: '/browse?p=0', // redirect back to the signup page if there is an error
failureFlash: true // allow flash messages
}));
app.post('/async/login', function(req, res, next) {
passport.authenticate('local-login', function(err, user, info, status) {
if (err) {
return res.send(err);
}
if (user) {
user.local = null;
return res.send(user);
} else {
return res.send(info);
}
})(req, res, next);
});
// =========================================================================
// passport session setup ==================================================
// =========================================================================
// required for persistent login sessions
// passport needs ability to serialize and unserialize users out of session
// used to serialize the user for the session
passport.serializeUser(function(user, done) {
done(null, user.id);
});
// used to deserialize the user
passport.deserializeUser(function(id, done) {
User.findById(id, function(err, user) {
done(err, user);
});
});
// =========================================================================
// LOCAL LOGIN =============================================================
// =========================================================================
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField: 'username',
passwordField: 'password',
passReqToCallback: true // allows us to pass in the req from our route (lets us check if a user is logged in or not)
},
function(req, email, password, done) {
// asynchronous
process.nextTick(function() {
User.findOne({
'local.email': email
}).populate({
path: 'spots comments currentLocation'
}).exec(function(err, user) {
// if there are any errors, return the error
if (err)
return done(err);
// if no user is found, return the message
if (!user)
return done(null, false, req.flash('loginMessage', 'No user found.'));
if (!user.validPassword(password))
return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.'));
// all is well, return user
else
User.populate(user, {
path: 'spots.bird',
model: 'Bird'
}, function(err, user) {
if (err)
return done(err);
else
User.populate(user, {
path: 'spots.location',
model: 'Location'
}, function(err, user) {
if (err)
return done(err);
else
console.log(util.inspect(user, showHidden = false, depth = 5, colorize = true));
return done(null, user);
});
});
});
});
}));
节点应用程序:
app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(cookieParser());
sessionVars = {
keys: ['<removed>'],
//secureProxy: true, // if you do SSL outside of node
maxAge: 2592000000
};
app.use(session(sessionVars));
app.use(flash());
require('./../modules/auth/passport')(passport);
app.use(passport.initialize());
app.use(passport.session());
有人知道为什么吗
更新:异步路由似乎没有调用解释一切的serializeUser函数!。有人知道如何强制序列化吗
如果我尝试直接调用:passport.serializeUseruser,done,那么我需要done参数,它在routes文件中不可用,尽管我可以传递它
是否有人知道,如果使用passport策略,serializeUser将被理所当然地调用?因此,我发现如果使用自定义形式的authenticate函数:
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
app.post('/login',
passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' }));
它似乎没有通过您提供的serializeUser函数传递它。会话的cookie会一直保存在浏览器中,并且会不断更改,即使您已注销,因为它们可能仍在“跟踪”您的行为
如果使用函数的“黑盒”版本:
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
app.post('/login',
passport.authenticate('local', { successRedirect: '/',
failureRedirect: '/login' }));
这是因为它会自动调用serializeUser。它是否与saveUninitialized或ResSave选项相关?检查有关这些参数的文档,尝试将它们设置为false以查看是否有更改。谢谢@WaldoJeffers。我和这些人玩了一场,但似乎不是。。。但这是一个很好的建议