【问题标题】:Passport.js, Express.js, and Angular.js routing: how can they coexist?Passport.js、Express.js 和 Angular.js 路由:它们如何共存?
【发布时间】:2017-01-11 19:09:39
【问题描述】:

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

背景:基于 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 上报告为问题。那里已经发布了一些额外的尝试,但还没有完全修复。

【问题讨论】:

  • Angular 如何拦截重定向?您是否在您的 Express 应用程序中定义了 '/profile' 路由?它有什么作用?
  • 我在 Angular 中有一个 /profile 路由,在 Express 中没有 /profile 路由,在 Express 中有一个 app.get('*',..) 路由。它以角度提供默认路由:.otherwise({ redirectTo: '/'});。任何尝试使用 Express 中的 res.renderres.redirect(to a specific angular view) 都是徒劳的。

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


【解决方案1】:

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

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

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

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

希望这能让你开始。

【讨论】:

  • 感谢您的详细解答。我尝试了您的建议,即使用#/profile,但运气不佳。我从服务器上的记录器中注意到路由/profile(或#/profile)从未被调用。我怀疑是不是因为Express没有这样的路由,所以我实现了一个简单的路由app.get('/profile', function(req,res){res.render(some html page);}。在这种情况下也没有运气。
  • 加一个用于引用 pushState api。不知道路由是如何在 Angular 中工作的!
【解决方案2】:

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

阅读this post

【讨论】:

猜你喜欢
  • 2013-07-13
  • 2016-09-10
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 2020-04-14
  • 1970-01-01
  • 2013-05-12
  • 2011-10-26
相关资源
最近更新 更多