Node.js Passport 的 Google 策略上的自定义 returnUrl

Posted

技术标签:

【中文标题】Node.js Passport 的 Google 策略上的自定义 returnUrl【英文标题】:Custom returnUrl on Node.js Passport's Google strategy 【发布时间】:2012-04-10 18:12:14 【问题描述】:

我正在使用 Express 和 Passport OpenID Google 策略,我想在每个身份验证请求上设置 returnURL,以便能够返回到启动该身份验证的页面。

情况是我有带有 Node.js 后端的 html5 幻灯片应用程序(以及社交内容和编辑器以及门户和扩展...https://github.com/bubersson/humla),我希望能够在某些幻灯片上登录用户(通过幻灯片menu...) 但我希望他能轻松回到同一张幻灯片。

所以我需要这样的东西?

app.get('/auth/google', function(req,res) 
   var cust = "http://localhost:1338/"+req.params.xxx;
   passport.authenticate('google', returnURL:cust, function ...
 

我已阅读 Passport 的指南,但仍然不知道该怎么做。我知道这不安全,但我还能怎么做呢?

或者我怎样才能让应用程序返回到启动登录的页面?或者有没有办法使用 AJAX 进行 OpenID 身份验证(并且仍然可以使用护照)?

【问题讨论】:

【参考方案1】:

无论您在哪里有登录按钮,都将请求的当前 URL 附加为 查询参数(根据您使用的任何模板系统进行调整):

<a href='/auth/google?redirect=<%= req.url %>'>Log In</a>

然后,将中间件添加到您的 GET /auth/google 处理程序中,该处理程序将该值存储在 req.session:

app.get('/auth/google', function(req, res, next) 
  req.session.redirect = req.query.redirect;
  next();
, passport.authenticate('google'));

最后,在您的回调处理程序中,重定向到存储在会话中的 URL:

app.get('/auth/google/callback', passport.authenticate('google',
  failureRedirect: '/'
), function (req, res) 
  res.redirect(req.session.redirect || '/');
  delete req.session.redirect;
);

【讨论】:

是否可以在没有会话的情况下执行此操作?【参考方案2】:

根据作者的说法,这对于 OpenID 策略是不可能的。我们设法通过直接访问变量来动态更新这些:

app.get('/auth/google', function(req, res, next) 
  passport._strategies['google']._relyingParty.returnUrl = 'http://localhost:3000/test';
  passport._strategies['google']._relyingParty.realm = 'http://localhost:3000';
  passport.authenticate('google')(req, res, next);
);

【讨论】:

【参考方案3】:

我已经为我的应用程序 Twitter 身份验证解决了这个问题,我确信 GoogleStrategy 非常相似。试试这个的变体:

假设您已经像这样定义了来自身份验证服务的回调路由(来自护照指南):

app.get('/auth/twitter/callback',
  passport.authenticate('twitter', 
      successRedirect: authenticationRedirect(req, '/account')
    , failureRedirect: '/'
  )
);

只需将该块更改为:

app.get('/auth/twitter/callback', function(req, res, next)
  passport.authenticate('twitter', function(err, user, info)
    // This is the default destination upon successful login.
    var redirectUrl = '/account';

    if (err)  return next(err); 
    if (!user)  return res.redirect('/'); 

    // If we have previously stored a redirectUrl, use that, 
    // otherwise, use the default.
    if (req.session.redirectUrl) 
      redirectUrl = req.session.redirectUrl;
      req.session.redirectUrl = null;
    
    req.logIn(user, function(err)
      if (err)  return next(err); 
    );
    res.redirect(redirectUrl);
  )(req, res, next);
);

现在,为经过身份验证的路由定义中间件,以将原始 URL 存储在会话中,如下所示:

ensureAuthenticated = function (req, res, next) 
  if (req.isAuthenticated())  return next(); 

  // If the user is not authenticated, then we will start the authentication
  // process.  Before we do, let's store this originally requested URL in the
  // session so we know where to return the user later.

  req.session.redirectUrl = req.url;

  // Resume normal authentication...

  logger.info('User is not authenticated.');
  req.flash("warn", "You must be logged-in to do that.");
  res.redirect('/');

有效!

【讨论】:

这很好用,但是在重定向时,如果用户被发送出去进行身份验证并返回,它似乎缺少哈希参数。登录后重定向时,是否有某种方法可以将它们保留在 URL 中? ***.com/questions/14124932/… @user645715 可以尝试使用req.session.redirectUrl = req.originalUrl;req.url【参考方案4】:

passport.authenticate 的回调中尝试res.redirect('back');

【讨论】:

谢谢!显然,在第一个和第二个 OpenID 请求之间设置了反向路由。我不知道!谢谢 嗯,我发现了这个问题。只有当我已经使用 Google 登录时,它才有效。如果护照重定向到谷歌页面,然后返回到我的网站 - “页面”路线丢失。是否有其他方法可以强制它从 Google 返回到我的位置(启动登录的页面)? @bubersson,如果我理解正确的话,您需要使用更主动的方法,例如第一个答案中的方法。

以上是关于Node.js Passport 的 Google 策略上的自定义 returnUrl的主要内容,如果未能解决你的问题,请参考以下文章

使用 passport.js 将本地策略连接到另一个(Facebook、Twitter、Google 等)

如何允许用户在 Node JS Passport JS 失败后尝试不同的电子邮件?

我可以使用 passport-google 回调来验证 android/ios 用户吗?

Passport & JWT & Google/Facebook 策略 - 如何结合 JWT 和 Google/Facebook 策略?

Node.js 和 Passport 对象没有方法 validPassword

如何使用 Passport.js 在 Node.js 中重置/更改密码?