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

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

背景 :基于MEAN堆栈的应用程序,试图使用Passport.js来授权 Facebooklogin。

Passport.js 指南后,我实现了类似于:

// 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路由。 显然,授权工作正常。 但是,redirect不起作用,因为路由由Angular处理。 授权后,我从来没有登陆/profile (但在默认的Angular路线)。

因此,我尝试使用Passport.js中提供的自定义callback,希望将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解释说,显然自定义的callback函数用于本地login。 但是你看到这个问题了吗? 我从Angular调用/connect/facebook ,但是我应该从/connect/facebook/callback收到一些json。

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

编辑 :在Passport-Facebook GitHub帐户上报告了同样的问题。 在那里发布了一些额外的尝试,但尚未完成修复。

这比一个答案中可以描述的更深一点,但是我会尝试开始指引你朝着正确的方向。

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

鉴于此,如果您已经调用了服务器路由,那么您不在Angular.js脚本中,并且任何再次加载angular度脚本的调用都将从一开始就开始。 如果没有完整的重新加载,你实际上无法从服务器调用你的Angular.js路由。 因此,你真的在​​这里做一个双重路线redirect。 您的服务器应该调用它的angular度的默认路由,追加/#/someroute到呼叫。 angular.js页面将加载,parsing/# ,并redirect到正确的angular度路线。 但请记住,如果对已经加载的对象有任何依赖关系,则这些对象不再存在于内存中。 因此,以这种方式访问​​的任何路由都应该像进入应用程序的入口一样运行。

实际上,您应该尝试使用successRedirect : '#/profile' ,请记住,angular度中的profilepath应视为应用程序入口点。

希望这会让你开始。

如果@ Claies的方式不工作,是否有可能你没有摆脱从Facebook的callback# =片段。

阅读这篇文章