Экспресс 4 + Паспорт, req.user не определен - порядок вызова функции?
Я столкнулся с очень специфической проблемой. Я пытался получить экспресс + паспорт на работу. Поскольку подавляющее большинство примеров в Интернете были для экспресс-3, процесс занял у меня какое-то время - в конце концов я заставил Google аутентификацию работать. Я пытался привязать учетную запись Google к локальной учетной записи, что требует поиска учетной записи из БД Mongo. Ниже приведена часть кода, которая работает:
//Serialize function
passport.serializeUser(function(user, done) {
done(null, user);
});
//Deserialize function
passport.deserializeUser(function(obj, done) {
done(null, obj);
});
//Strategy
passport.use(new GoogleStrategy({
returnURL: 'http://localhost:8000/auth/google/return',
realm: 'http://localhost:8000/'
},
function(identifier, profile, done) {
process.nextTick(function() {
profile.identifier = identifier;
return done(null, profile);
});
}
));
Следующие коды были проверены для работы. Все работает как шарм. Однако, когда я изменил код следующим образом:
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
//note that only change is to find user from database, User is a mongoose instance
//very straightforward, verified user can be found.
User.findById(id, function(err, user) {
done(err, user);
});
});
И стратегия была изменена, чтобы создать пользователя, если не найден:
process.nextTick(function() {
profile.id = identifier;
User.findOne({
'google.id': profile.id
}, function(err, user) {
if (err) {
return done(err); // don't even know what done means!
} else if (user) {
return done(null, user);
} else {
//very easy to create and save to database.
//create a new user instance
var newUser = new User();
newUser.google.id = profile.id;
newUser.google.name = profile.displayName;
newUser.google.email = profile.emails[0].value;
newUser.local.email = newUser.google.email;
newUser.local.name = newUser.google.name;
// newUser.id = newUser._id;
//it should have been saved to database?
newUser.save(function(err) {
if (err)
throw err;
//The done is called once is saved.
return done(null, newUser);
});
}
});
});
И это тот роутер, который был размещен после всей необходимой инициализации для паспорта.
app.get('/', function(req, res) {
console.log("Rendering...");
console.log(req.user);
res.render('index', {
user: req.user
});
console.log("Rendering done...");
});
Теперь вот забавная часть: когда я получаю доступ к URL
, console.log в пределах app.get('/')
был назван ПОСЛЕ загрузки страницы, и req.user
НЕ является неопределенным. Когда он работал, console.log вызывался в правильном порядке. Кажется, что когда страница была отображена, req.user
еще не был инициализирован - но я просто не могу понять, почему функции console.log назывались AFTER res.render - для меня это не имеет никакого смысла. Это может быть результатом некоторой асинхронной логики...
У кого-нибудь есть идеи? Спасибо. Я обновлю код Github
,
Я тоже пробовал websocket
чтобы получить доступ req.handshake.use
r - все данные есть. Это как-то просто когда res.render
был вызван, он еще не был инициализирован.