req.user未定义 - node + express + passport-facebook

14

我正在尝试让护照(passport)与我的Node Express服务器配合工作。 我可以使用Facebook登录并在我的数据库中找到正确的用户; 但是,当我重定向后,req.user始终未定义。 这是我的服务器代码:

var express = require('express'),
path = require('path'),
http = require('http'),
passport = require('passport'),
FacebookStrategy = require('passport-facebook').Strategy,
user = require('./routes/users');


var app = express();

passport.use(new FacebookStrategy({
    clientID: "HIDDEN",
    clientSecret: "HIDDEN",
    callbackURL: "http://MYURL.com/auth/facebook/callback",
    passReqToCallback: true
 },
  function(req, accessToken, refreshToken, profile, done) {
    user.findOrCreate(profile, function(err, user) {      
      if (err) { return done(err); }      
      done(null, user);
    });    
  }
));

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

passport.deserializeUser(function(id, done) {
  user.findById(id, function(err, user) {
    done(err, user);
  });
});

app.configure(function () {    
app.set('port', process.env.PORT || 3000);
    app.use(express.static(path.join(__dirname, 'public')));
    app.use(express.logger('dev')); /* 'default', 'short', 'tiny', 'dev' */
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.session({ secret: 'foobar' }));   
    app.use(passport.initialize());
    app.use(passport.session()); 
    app.use(app.router);    
});

app.get('/auth/user', function (req, res) {
    console.log(req);
});

app.get('/auth/facebook', passport.authenticate('facebook'));
app.get('/auth/facebook/callback', 
  passport.authenticate('facebook', { successRedirect: '/',
                                      failureRedirect: '/login' }));


http.createServer(app).listen(app.get('port'), function () {
    console.log("Express server listening on port " + app.get('port'));
});

我访问 /auth/facebook,它找到了正确的用户并将我重定向到 /。但是当我访问 /auth/user 时,req.user 是未定义的,并且我的会话显示如下:

cookies: { 'connect.sid': 's:JFdQkihKQQyR4q70q7h2zWFt.VS+te0pT0z/Gtwg7w5B33naCvA/ckKMk60SFenObxUU' },
  signedCookies: {},
  url: '/auth/user',
  method: 'GET',
  sessionStore:
   { sessions:
      { '5sk3Txa2vs5sYhvtdYwGaUZx': '{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"passport":{"user":"50c527c9c6cb41860b000001"}}',
        'Au6m0hAj/3warKOGNSWw0yu2': '{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"passport":{}}',
        JFdQkihKQQyR4q70q7h2zWFt: '{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"passport":{}}' },
     generate: [Function],
     _events: { disconnect: [Function], connect: [Function] } },
  sessionID: 'JFdQkihKQQyR4q70q7h2zWFt',

这是否与我的sessionID不匹配与设置了passport用户的会话有关?

更新

我确定sessionID不匹配是因为我在c9.io上运行我的代码,实际上它有两个URL。 当我使用正确的URL并转到/auth/user时,我的sessionID与设置了passport用户的会话匹配,在日志中可以看到deserializeUser找到了正确的用户对象。 然而,req.user 在此之后仍然未定义。

Trying to find user with id: 50c527c9c6cb41860b000001
{ sessions:
   { yoOUOxyXZ0SmutA0t5xUr6nI: '{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"passport":{"user":"50c527c9c6cb41860b000001"}}',
     goZpmK3y3tOfn660hRbz2hSa: '{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"passport":{}}',
     'O5Sz1GuZqUO8aOw4Vm/hriuC': '{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"passport":{}}' },
  generate: [Function],
  _events: { disconnect: [Function], connect: [Function] } }
sessionID: yoOUOxyXZ0SmutA0t5xUr6nI
req.user: undefined
{ cookie:
   { path: '/',
     _expires: null,
     originalMaxAge: null,
     httpOnly: true },
  passport: {} }

更新2

我找到了问题所在。它出现在我的user.findByID函数中:

exports.findById = function(id, callback) {    
    console.log('Trying to find user with id: ' + id);
    db.collection('users').findOne({'_id':id}, function(err, user) {           
            callback(err, user);
    });
};

更改为:

exports.findById = function(id, callback) {    
    console.log('Trying to find user with id: ' + id);
    db.collection('users').findOne({'_id':new BSON.ObjectID(id)}, function(err, user) {           
            callback(err, user);
    });
};

3
另外一个注意事项:要注意定义表达路由的顺序——当你定义app.get或其他路由时,它确实很重要。你可以在Passport中间件之前定义用户路由,这样在此路由中就不会有用户数据。(这并非特指您的情况,但症状非常相似)。 - moka
2
现在它能正常工作了吗?如果是这样,请将其发布为答案。 - Emil Condrea
一个方便的工具是将你的节点复制并粘贴到 JSHint http://www.jshint.com 中。你也可以运行 grunt 任务来让 JSHint 监视你的代码。 - AJ.
使用mongoosejs,您可以避免这种情况。 - kberg
1个回答

1

正如您在更新中所说的那样,是用户._id变量格式不正确。为了避免这种情况,并且在其他请求和方法中稍后需要处理此格式,我建议您在注册时生成一个新的用户ID。

您可以使用此模块:

node-uuid

var uuid = require('node-uuid');

function findOrCreate(profile, callback) {
  // save new profile
  profile.uid = uuid.v1().replace(/\-/g, '');
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接