Passport.js,Express.js和Angular.js路由:它们如何共存?

时间:2015-01-17 10:25:25

标签: angularjs node.js express passport.js passport-facebook

我道歉这个问题有点长,但我已经研究了一段时间了,真的需要解释所有的故事。

后台:基于MEAN堆栈的应用,尝试使用Passport.js 授权 Facebook登录。

在Passport.js guide之后,我实施了类似的内容:

// HTML
    <a href="/connect/facebook" target="_self">Add a Facebook login</a>
// send to facebook to do the authentication
app.get('/connect/facebook',isLoggedIn, passport.authorize('facebook', 
    { scope : 'email' })
);
// handle the callback after facebook has authorized the user
app.get('/connect/facebook/callback',
    passport.authorize('facebook', {
    successRedirect : '/profile',
    failureRedirect : '/profile'
    }));

注意html中的target=_self以跳过Angular路由。 显然,授权工作正常。但是,重定向不起作用,因为路由由Angular处理。授权后,我永远不会登陆/profile(但在默认的Angular路线上)。

因此,我尝试使用Passport.js here建议的自定义回调,希望将json数据传递给Angular,并让Angular进行路由。我最终做了类似的事情:

// In the controller
$http.get("/connect/facebook").success(function(data){
    // here I wait for json data from the server and do the routing
});
// I call this route from Angular
app.get('/connect/facebook',isLoggedIn,passport.authorize('facebook', 
    { scope : 'email' })
);
// But Facebook lands here!
app.get('/connect/facebook/callback',function(req, res, next) {
    passport.authorize('facebook', function(err, user, info) {
        res.json({something:smtg});
        ...

显然,自定义回调适用于本地登录,如Passport.js所述。但是你在这看到问题了吗?我从Angular打电话给/connect/facebook,但是我应该从/connect/facebook/callback收到一些json。

我即将放弃Passport,但在此之前,您是否看到任何允许在FB授权后登陆/profile的解决方案,也许是自定义消息?非常感谢您的阅读。

修改Passport-Facebook GitHub account报告了同一个问题。在那里发布了一些额外的尝试,但还没有完全修复。

2 个答案:

答案 0 :(得分:5)

这比一个答案中描述的更深入,但我会尝试开始指向正确的方向。

基本上,Angular.js路由根本不是HTML路由,而是恰好使用URL来使用最终用户的内部路由结构。请记住,Angular.js是一个客户端脚本,并且不需要整页重新加载,因为这将重新加载整个脚本。因此,/#用于欺骗浏览器跳转到已加载脚本中的特定代码位。 (与HTML文档中的传统锚点位置相对)。不幸的是(或者幸运的是),HTML 5模式允许您隐藏网址的/#部分,因此您只需看http://somesite.com/#/someroute而不是http://somesite.com/someroute。但请放心,/#仍在那里。 Angular.js使用HTML5 pushState(AKA HistoryAPI)来执行魔术替换。

鉴于此,如果您已调用服务器路由,则您在Angular.js脚本之外,并且任何再次加载角度脚本的调用将从头开始。您无法在没有完全重新加载的情况下从服务器实际调用Angular.js路由。因此,您实际上在这里进行双重路由重定向。您的服务器应该调用它的角度默认路由,将/#/someroute附加到呼叫中。 angular.js页面将加载,解析/#,并重定向到正确的角度路径。但请记住,如果对已加载的对象存在任何依赖性,则这些对象不再存在于内存中。因此,以这种方式访问​​的任何路由都应该像应用程序的入口点一样运行。

实际上,您应该尝试使用successRedirect : '#/profile',请注意角度中的profile路径应被视为应用入口点。

希望这能让你开始。

答案 1 :(得分:0)

如果@ Claies的方式不起作用,你是否有可能没有从facebook回调中删除# = 片段。

阅读this post