node.js - 使用 PassportJS 和 Connect for NodeJS 对 Facebook 用户进行身份验证

标签 node.js facebook connect passport.js

我正在尝试使用连接将 passport 集成到我的 nodejs 服务器中,但似乎无法正确完成。所有指南/示例都使用 expressJS,因此我尽力重新格式化代码以使用我的代码,但我似乎无法让它工作。相关部分写在下面。有人对可能出现的问题有什么建议吗? passport.authenticate() 似乎永远不会被调用(至少 facebook 身份验证回调中的 console.log 消息永远不会打印)。我目前没有将任何内容保存到数据库中,因此这个问题应该是我所遗漏的非常简单的问题。

唯一想到的是我对 facebook 的潜在回调,这是一个本地主机 url(因为我仍在本地开发它)。我能够使用 everyauth(从纯本地实例)很好地通过 facebook 进行身份验证,但切换到 passportJS,因为我遇到了 passportJS 似乎可以解决的不同问题。

passport = require('passport');
  fpass = require('passport-facebook').Strategy;

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

passport.use(new fpass({
        clientID:'facebook app id',
        clientSecret:'facebook app secret',
        callbackURL:'http://localhost:3000/auth/facebook/callback'
    },
    function(accessToken, refreshToken, fbUserData, done){
        console.log('got here');
        return done(null,fbUserData);
    }
));



    function checkLoggedIn(req, res, next){
        console.log("req.user: " + req.user);
        if(req.user)
            next();
        else{
            console.log('\nNot LOGGED IN\n');
            if(req.socket.remoteAddress || req.socket.socket.remoteAddress == '127.0.0.1'){
                var folder,contentType;
                console.log('req url = '+req.url);
                if(req.url == '/'){
                    folder = __dirname + '/landingPage.html';
                    contentType = 'text/html';
                }
                else if(req.url == '/auth/facebook'){
                    passport.authenticate('facebook');
                    return;
                }
                else if(req.url == '/auth/facebook/callback'){
                    passport.authenticate('facebook', {failureRedirect: '/failbook', successRedirect:'/'});
                    return;
                }
                if(folder){
                    console.log('got to folder part\n\n');
                    fs.readFile(folder, function(error, content){
                      if(error){
                        res.writeHead(500);
                        res.end();
                      }
                      else{
                        res.writeHead(200, {'Content-Type': contentType});
                        res.end(content);
                      }
                    });
                  }
                    else{ res.writeHead(500); res.end();}
            }
            else {res.writeHead(500); res.end();}
        }
    }

  connect.createServer(
    connect.cookieParser(),
    connect.bodyParser(),
    connect.session({secret:'wakajakamadaka'}),
    passport.initialize(),
    passport.session(),
    checkLoggedIn).listen(8888);
  console.log('Server has started.');
}

有没有人有任何建议或发现我正在做的事情有问题?我的其他两个选择是切换回 everyauth 并弄清楚那里发生了什么,或者切换到 ExpressJS,但我宁愿不选择这两个选项中的任何一个。

最好的,
萨米

最佳答案

passport.authenticate 返回一个通常在中间件链中使用的函数,该函数由 Express 通过 reqres 调用。

它将在其他中间件或路由处理程序中独立工作,例如您的 checkLoggedIn 函数,但您必须显式调用 req 返回的函数, resnext 让它处理请求。

else if(req.url == '/auth/facebook'){
  // NOTE: call the function returned to process the request
  passport.authenticate('facebook')(req, res, next);
  return;
}

其他方面看起来不错。让我知道这是否能让您启动并运行。


更新

Jared 在 stackoverflow 之外帮了我一点忙,我们已经完全解决了这个问题。我正在更新此答案以包含我们发现的新信息。


1) 一个问题显然是 redirect() 中间件存在于 Express 而不是 Connect(至少不是当前版本)。使用连接时,您需要将 PassportJS 模块中 authenticate.js 的第 97 行从 return res.redirect(options.successRedirect); 更改为:

var redirect = function(redirectionURL){
    res.writeHead(302, {'location':redirectionURL});
    res.end();             
}

return redirect(options.successRedirect);

注意 - 上面的 options.successRedirect 与回调函数代码中的 successRedirect 相同。这将是行 passport.authenticate('facebook', {failureRedirect: '/failbook', successRedirect:'/'}); 我问题中的代码。


2) 另一个是我在我的应用程序中使用集群模块(上面的代码片段中没有显示)。这意味着 nodeJS 应用程序无法正确读取 session 数据,这导致了我的问题。 这个问题会影响任何依赖 session 的库,包括所有其他使用 session 的身份验证模块(例如 everyauth、connect-auth 等)我将引用 Jared 的解决方案:

Quick reply: are you using cluster or spinning up multiple server instances?

If so, the built-in MemoryStore for the session won't work properly, and you need to switch to something like this: https://github.com/visionmedia/connect-redis

Or one of the other session stores listed here: https://github.com/senchalabs/connect/wiki

The reason is that you'll end up hitting a server which didn't serve the original request, and thus doesn't have that session information in its own memory. That sounds like what could be going on if deserializeUser isn't called 100% of the time.

希望这能帮助到这里的人!

关于node.js - 使用 PassportJS 和 Connect for NodeJS 对 Facebook 用户进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11006318/

相关文章:

mysql - 我们可以在使用 sequelize js Node 在 mysql 表中插入数据后给时间吗

javascript - 钛 - Facebook 授权() - "An error occurred"

ruby-on-rails - OmniAuth Facebook 作为弹出窗口

node.js - 在 express.js 中,有什么方法可以在一个函数中同时捕获对 json 和 html 的请求?

Java URLConnection - 我什么时候需要使用 connect() 方法?

node.js - 在 'data' 事件中,为什么数据大小是 1374 的倍数?

javascript - Javascript 中的 Mysql 日期时间不同

node.js - Node (套接字)实时音频流/广播

javascript - 将事件个人资料图片发布到页面 javascript sdk 时出现问题

node.js - Connect 中的响应重定向