当前位置: 首页 > 知识库问答 >
问题:

使用PassportJS with Connect for NodeJS对Facebook用户进行身份验证

申屠洛华
2023-03-14

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

唯一想到的是我对facebook的潜在回调,这是一个localhost的网址(因为我仍在本地开发)。我能够用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,但我不想使用这两个选项中的任何一个。


萨米

共有1个答案

程旭尧
2023-03-14

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

它将在其他中间件或路由处理程序中独立工作,例如您的check LoggedIn函数,但是您必须显式调用返回的函数,其中包含reqresNext以使其处理请求。

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中(至少不是当前版本)。使用connect时,需要更改authenticate的第97行。来自的PassportJS模块中的js返回res.redirect(options.successRedirect) 至:

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

return redirect(options.successRedirect);

注意-选项。上面的successRedirect与回调函数代码中的successRedirect相同。这将是第行passport。验证('facebook',{failureRedirect:'/failbook',successRedirect:'/'}) 在我问题中的代码中。


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

快速回复:您是使用集群还是旋转多个服务器实例?

如果是这样,会话的内置MemoryStore将无法正常工作,您需要切换到这样的内容:https://github.com/visionmedia/connect-redis

或此处列出的其他会话存储之一:https://github.com/senchalabs/connect/wiki

原因是,您最终将访问一个未提供原始请求的服务器,因此其内存中没有该会话信息。如果反序列化用户没有100%的时间被调用,这听起来像是发生了什么。

希望这对来这里的人有帮助!

 类似资料:
  • null 我研究了OAuth2隐式授权,但它要求用户在成功验证后批准/拒绝应用程序。它在我的情况下不起作用,因为我同时拥有应用程序和API。 我查看了OAuth2密码授权,它并不完美,因为我需要公开client_id/client_secret。 我关注OAuth2的原因是因为该API最终将是公开的。 忘记OAuth2,在用户发布用户名/密码时手动生成access_token(在本例中,当API公

  • 这是服务到服务身份验证中概述的规则的一个例外吗?该规则规定需要设置为接收服务的url(例如https://xxxxx.run.app)。和是一回事吗? 最后,除了使用googlecloudsdk(即imaging不存在)之外,是否还有其他方法使用用户帐户而不是服务帐户进行身份验证?

  • 我试图建立一个认证系统与Laravel 4与Facebook登录。我正在使用Laravel 4的madewith love/laravel-oAuth2包。 当然,当用户登录Facebook时,没有密码可以添加到我的数据库中。但是,我正在尝试检查数据库中是否已经有用户id,以确定是否应该创建一个新实体,或者只是登录当前实体。我想使用Auth命令来实现这一点。我有一张叫做“粉丝”的桌子。 这就是我正

  • 我正在尝试使用urllib3连接到网页。代码如下所示。 如果我们假设url是需要使用用户名和密码进行身份验证的某个网页,那么我是否使用正确的代码进行身份验证? 我使用urllib2做这件事很舒服,但使用urllib3做不到同样的事情。 非常感谢

  • jwt不应该仅仅用于认证用户吗?我读到过可以在里面存储非敏感的东西,比如用户ID。将权限级别之类的东西存储在令牌中可以吗?这样我可以避免数据库调用。

  • 我正在使用vue3,并且已经建立了一个AWS用户池(amazoncognito.com)。目标是根据Cognito使用用户名和密码对用户进行身份验证,并接收OAuth2令牌以验证针对AWSAPI网关发出的API请求。 挑战:AWS amplify似乎不适用于最新的vue3版本。它只显示用户未登录,但未显示任何登录或注销按钮,无论配置如何。 我感兴趣的潜在解决方案(优先顺序) main.js 和内部