为什么我的req.user在加载时始终为空?

我已经挣扎了好几天,取得了一些很好的进展,但是我不能让我的课程工作得很好。

我已经成功地使用Passport来与Facebook进行身份validation。 当我用FBbutton点击我的login时,会话完全加载,我有我的req.user对象都准备好去,但在我看来,我应该只需要做一次。

我知道护照保存了一个cookie。 我已经看了看,看到工作。

我试图检测用户是否已经login在我的索引页的负载,但是当我加载页面的req.user对象始终为空,我的passport.deserializeUser方法永远不会被调用来加载它(如果我点击login到FBbutton它确实被调用)。

所以我的问题是,你如何告诉护照页面加载检查cookie和加载用户会话,如果有的话?


更新 – 好的,所以对于那些稍后发现这个问题的人,我只想回顾一下我在这里学到的东西(感谢那些评论过的人)。 希望这会帮助其他人。

我习惯了不pipe服务器如何生存的.NET cookies。 Node.js和护照不在同一个前提下工作。 默认情况下,node.js使用内存来保持会话。 当您closuresterminal/命令行中的节点(每次更改服务器代码时都必须执行此操作)时,内存存储cookie信息将被重置,因此任何与其关联的cookie都是无意义的。

为了解决这个问题,我安装了Redis( http://cook.coredump.me/post/18886668039/brew-install-redis ),并把它作为我的商店( http://www.hacksparrow.com/use-redisstore-而不是memorystore-express-js-in-production.html )。

这将在Azure上工作,这是我计划的生产服务器,因此一切正常。


好的,这是一些代码。 我不确定放什么部分…

这是server.js

/** * Module dependencies. */ var express = require('express') , app = express() , partials = require('express-partials') , http = require('http') , server = http.createServer(app) , io = require('socket.io').listen(server) , routes = require('./routes') // facebook , passport = require('passport') , facebookStrategy = require('passport-facebook').Strategy // custom stuff , urlCommand = require('./middleware/UrlCommand') , azureCommand = require('./middleware/AzureCommand') , userCommand = require('./middleware/UserCommand'); // Ports var port = process.env.port; if (isNaN(port)) port = 3000; server.listen(port); //allows the use of Layouts app.use(partials()); passport.serializeUser(function(user, done) { done(null, user.RowKey); }); passport.deserializeUser(function (id, done) { console.log("deserialize"); userCommand.findByID(id, function (err, user) { done(err, user); }); }); // Configuration app.configure(function () { app.set('views', __dirname + '/views'); app.set('view engine', 'jade'); app.use(express.cookieParser()); app.use(express.bodyParser()); app.use(express.session({ secret: 'SECRET!' })); app.use(express.methodOverride()); app.use(passport.initialize()); app.use(passport.session()); app.use(app.router); app.use(express.static(__dirname + '/public')); }); app.configure('development', function(){ app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); }); app.configure('production', function(){ app.use(express.errorHandler()); }); // Facebook passport.use(new facebookStrategy({ clientID: CLIENT, clientSecret: "SECRET", callbackURL: "http://localhost:3000/auth/facebook/callback" //DEV }, function (accessToken, refreshToken, profile, done) { userCommand.findOrCreate(profile.id, profile.name.givenName, profile.name.familyName, profile.emails[0].value, accessToken, function (error, user) { return done(null, user); }); } )); // Routes app.get('/', routes.index); app.get('/auth/facebook', passport.authenticate('facebook', { scope: 'email' })); app.get('/auth/facebook/callback', passport.authenticate('facebook', { successRedirect: '/', failureRedirect: '/login' })); // Sockets io.sockets.on('connection', function (socket) { // when the client emits 'sendURL', this listens and executes socket.on('sendURL', function (data) { console.log('sendURL called: ' + data); urlCommand.AddURL(data); // we tell the client to execute 'processURL' io.sockets.emit('urlComplete', data); }); }); console.log("Express server listening on port %d in %s mode", port, app.settings.env); 

index.js

 exports.index = function (req, res) { console.log(req.user); // ALWAYS NULL res.render('index', { title: 'Express' }) }; 

UserCommand

 var azureCommand = require('../middleware/AzureCommand'); var tableService = azureCommand.CreateTableService(); function findByID(id, callback) { console.log('FindByID'); tableService.queryEntity('user', 'user', id, function (error, entity) { console.log('Found him: ' + entity.Email); callback(error, entity); }); } function findOrCreate(id, first, last, email, accessToken, callback) { var user = { PartitionKey: 'user' , RowKey: id , First: first , Last: last , Email: email , AccessToken: accessToken } tableService.insertEntity('user', user, function (error) { callback(null, user); }); } exports.findByID = findByID; exports.findOrCreate = findOrCreate; 

这是我的输出日志显示当我输出我的会议…

 node server.js info - socket.io started Express server listening on port 3000 in development mode { cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true }, passport: {} } debug - served static content /socket.io.js 

问题出在你的serializeUserdeserializeUser函数中。

正如你注意到的那样,当你点击FBloginbutton时,deserializeUser被调用了第一次也是唯一一次 – 实际上它是用一个已经被serializeUser函数返回的id调用的。 如果此时它将无法通过所提供的idfind用户, passport.user将不会被保存到会话中。

因此,在下面的请求中, passport.deserializeUser根本不会被调用,因为express.session不会填充对护照用户ID的req.session

总结一下 :你需要检查你的serializeUser返回一个id ,而你的deserializeUser可以理解和反serializeUser这个id

仅供参考:经过身份validation的用户的正确req.user对象应如下所示:

 { cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true }, passport: { user: 51772291b3367f0000000001 } } 

那么,起初你应该发布一些代码,因为这个问题可能在任何地方。

比检查美丽的文件http://passportjs.org/guide/

尽pipe护照带来了很多例子通过github给你。

如果你想有一个完整的例子不同的身份validation方法,你应该访问https://github.com/madhums/nodejs-express-mongoose-demo