1

我已按照此处的建议成功链接Accounts到。如果登录用户使用 OAuth 2.0(例如 Google Contacts API)授权第 3 方,我可以将该信息保存在帐户中,然后将该帐户与登录用户绑定。Users

我想更进一步,使登录体验尽可能无缝。一旦用户将他们的身份绑定到第 3 方帐户,我希望他们不仅能够使用本地策略(用户名/密码)登录,然后提取相关的第 3 方信息,而且还可以通过其他方式:注销时,连接到 Google 将使他们以我的应用程序的用户身份登录,使 req.user = 他们的User信息,就像他们使用本地策略登录时一样。这是相关的代码块(显示的还有很多,但重点就在那里。

passport.use(new GoogleStrategy({
        clientID: google_params.client_id,
        clientSecret: google_params.client_secret,
        callbackURL: google_params.callbackURL,
        passReqToCallback: true
    },
    function(req, token, refreshToken, profile, done) {

...
        // If no user in session, set the req.user to the associated user
        User.findOne({
        'username': account.userId
        }, function(err, user) {
            console.log('Account exists already in DB, and is already tied to a user. Logging into users account.');
            req.user = user;
            return done(null, account);
        });

etc...

在检查序列化/反序列化函数时,此代码永远不会将用户或帐户信息序列化到会话中,因此虽然该信息确实在验证回调结束时传递,但它会在页面刷新时消失(再次,因为没有保存到会话中)。我该怎么办?我是否正确地考虑了这一点?

4

2 回答 2

1

答案有点晚了,但我一直在研究这个我正在构建的应用程序,它可能会帮助其他人。

所以答案是肯定的,您可以让用户链接他们的帐户,而无需他们创建本地帐户(如 Scotch.io 教程中所建议的)。诀窍是管理帐户的重复数据删除。

无论他们使用哪个提供商登录,我们都会按顺序处理以下检查:

  1. 如果此提供者已经存在用户:重新登录。
  2. 如果此提供商不存在用户:检查电子邮件地址(或提供商之间的其他公共字段)是否存在用户。如果是这样,链接帐户并登录。
  3. 如果此提供者或其他提供者还没有用户:使用从提供者中提取的信息创建一个新的用户模型,然后登录。

这应该为您支持的所有提供者完成。通过使用将由第三方服务(例如电子邮件地址)预先验证的通用字段,我们可以对帐户进行重复数据删除。另一个功能可能是允许用户手动将它们链接在一起,以应对他们想要链接具有不同电子邮件地址的帐户的情况(这在 github 上经常发生,他们使用个人帐户然后想将其连接到工作帐户,例如 CI 提供者)

希望这可以帮助。如果您找到替代解决方案,最好在此处添加它或者遇到任何问题。我认为这是一个足够常见的案例,它可以变成一个 wiki。

** 更新 **

如果您想将来自多个提供商的帐户“链接”在一起,此时您将需要一个包含特定于您的应用程序的用户记录的数据库,这些用户记录又与第三方帐户记录相关联。然后,在验证回调中,您需要执行任何必要的查询并提供您的应用程序特定的用户记录来完成。这将使事情保持一致,因此如果有人同时链接了 Facebook 和 Twitter,他们可以返回应用程序并使用其中任何一个登录。

关于该主题的进一步讨论在这里: http: //passportjs.org/guide/authorize.html

如果你走那条路线(就像我在我的应用程序中所做的那样),我会使用这样的中间件将身份验证和授权组合到一条路线中:

function authnOrAuthzFacebook(req, res, next) {
  if (!req.isAuthenticated()) {
    passport.authenticate('facebook', { successRedirect: '/settings/accounts',
                                        failureRedirect: '/login' })(req, res, next);
  } else {
    passport.authorize('facebook-authz')(req, res, next);
  }
}

app.get('/facebook-login', authnOrAuthzFacebook);

可以在 GitHub 上看到此评论所在的应用程序示例(最终版本)。

因此,有一些替代版本可以完成相同的工作(取决于您要如何处理它)。

于 2016-12-13T10:06:35.020 回答
0

看看这个教程:

http://scotch.io/tutorials/javascript/easy-node-authentication-linking-all-accounts-together

于 2014-06-09T14:55:50.233 回答