9

アプリのプロファイルページを作成したら、ユーザーが利用しているソーシャルサービスのリストを表示したいと思います。これには、Meteorの組み込みの会計システムを使用するのが最も簡単な方法だと思いました。

既存のアカウントに外部サービスを追加する良い方法はありますか?

また、ユーザーは、Facebook自分のパスワードのいずれかを使用してアプリからログインできるようになりますか?

当然続く別の質問:外部サービスで作成されたアカウントにアプリケーション固有のパスワードを追加する良い方法はありますか?

4

4 に答える 4

7

別の方法を次に示します。このソリューションでは、コア関数をオーバーライドし、いくつかのカスタム動作を追加しています。私の目標は、サービス データを現在ログインしているユーザーに関連付けて、コア機能が通常のように処理できるようにすることです。

orig_updateOrCreateUserFromExternalService = Accounts.updateOrCreateUserFromExternalService;
Accounts.updateOrCreateUserFromExternalService = function(serviceName, serviceData, options) {
  var loggedInUser = Meteor.user();
  if(loggedInUser && typeof(loggedInUser.services[serviceName]) === "undefined") {
    var setAttr = {};
    setAttr["services." + serviceName] = serviceData;
    Meteor.users.update(loggedInUser._id, {$set: setAttr});
  }
  return orig_updateOrCreateUserFromExternalService.apply(this, arguments);
}

長所:

  • 不要なアカウントの作成を回避
  • コードが短くてわかりやすい
  • この機能がMeteorコアに追加されている場合、コードは簡単に削除できます

短所:

  • ユーザーがログインする必要があります。ユーザーが最初に twitter でログインし、ログアウトしてから facebook でログインすると、2 つの別個のアカウントが作成されます。
  • コンピュータを共有しているユーザーは、意図せずにアカウントが統合される場合があります。
  • updateOrCreateUserFromExternalService の仕組みに関する知識に依存します。これはひどいことではありません - これは Meteor の公開 API の一部であるため、おそらく大幅に変更されることはありません (いずれにせよ頻繁ではありません)。しかし、それはまだ危険です。
于 2013-09-02T15:24:09.373 に答える
3

以下は、既存のユーザー アカウントに認証情報を追加する方法です: .../meteor-how-to-login-with-github-account.html

于 2013-07-21T12:06:54.817 に答える
1

はい、ユーザー アカウントは複数のサービスに関連付けることができ、パスワード ベースのログインを同時に行うことができます。Meteor docsでは、そのようなユーザー アカウントの構造を確認できます。

{
  _id: "bbca5d6a-2156-41c4-89da-0329e8c99a4f",  // Meteor.userId()
  username: "cool_kid_13", // unique name
  emails: [
    // each email address can only belong to one user.
    { address: "cool@example.com", verified: true },
    { address: "another@different.com", verified: false }
  ],
  createdAt: 1349761684042,
  profile: {
    // The profile is writable by the user by default.
    name: "Joe Schmoe"
  },
  services: {
    facebook: {
      id: "709050", // facebook id
      accessToken: "AAACCgdX7G2...AbV9AZDZD"
    },
    resume: {
      loginTokens: [
        { token: "97e8c205-c7e4-47c9-9bea-8e2ccc0694cd",
          when: 1349761684048 }
      ]
    }
  }
}

ユーザー名/パスワード ログインを既存のアカウントに追加するAccounts.sendResetPasswordEmailには、サーバー側で使用できます。これにより、変更が認証および承認されて発生することも保証されます。

もちろん、サーバー側のユーザー レコードを自分で新しいパスワードで更新することもできますが、これによりアプリにセキュリティ ホールが生じる可能性があります。また、可能であれば独自の暗号化プロトコルを実装しないことをお勧めします。難しいためです。

メール以外のサービスを追加したい場合は、たとえば

  1. 現在のユーザーの MongoDB ドキュメントにランダムな長いトークンを保存し、それをクライアントに返すサーバー メソッドを呼び出します。
  2. を使用して別のサービスでユーザーを再ログインしますAccounts.loginWith[OtherService]。これにより、他のサービスの新しいアカウントを使用して、ユーザーがログアウトし、再度ログインします。
  3. 最初のメソッドから返されたトークンをパラメーターとして使用して、2 番目のサーバー メソッドを呼び出します。この 2 番目の方法は、指定されたトークンを持つユーザー アカウントを検索し、そのデータを現在の (新しい) アカウントにマージします。
于 2013-03-24T15:38:55.357 に答える
0

この投稿の例と回答を確認してください。複数の外部および内部アカウントを統合するためのコードがほとんど提供されます。マイナーな調整により、必要に応じて各アカウントのパスワード フィールドを追加できます。

mrt:accounts-ui-bootstrap-dropdown で Meteor.loginWithGoogle を使用する方法

コード:

isProdEnv = function () {
    if (process.env.ROOT_URL == "http://localhost:3000") {
        return false;
    } else {
        return true;
    }
}

Accounts.loginServiceConfiguration.remove({
    service: 'google'
});

Accounts.loginServiceConfiguration.remove({
    service: 'facebook'
});

Accounts.loginServiceConfiguration.remove({
    service: 'twitter'
});

Accounts.loginServiceConfiguration.remove({
    service: 'github'
});

if (isProdEnv()) {
    Accounts.loginServiceConfiguration.insert({
        service: 'github',
        clientId: '00000',
        secret: '00000'
    });
    Accounts.loginServiceConfiguration.insert({
        service: 'twitter',
        consumerKey: '00000',
        secret: '00000'
    });
    Accounts.loginServiceConfiguration.insert({
        service: 'google',
        appId: '00000',
        secret: '00000'
    });
    Accounts.loginServiceConfiguration.insert({
        service: 'facebook',
        appId: '00000',
        secret: '00000'
    });
} else {
    // dev environment
    Accounts.loginServiceConfiguration.insert({
        service: 'github',
        clientId: '11111',
        secret: '11111'
    });
    Accounts.loginServiceConfiguration.insert({
        service: 'twitter',
        consumerKey: '11111',
        secret: '11111'
    });
    Accounts.loginServiceConfiguration.insert({
        service: 'google',
        clientId: '11111',
        secret: '11111'
    });
    Accounts.loginServiceConfiguration.insert({
        service: 'facebook',
        appId: '11111',
        secret: '11111'
    });
}

Accounts.onCreateUser(function (options, user) {
    if (user.services) {
        if (options.profile) {
            user.profile = options.profile
        }
        var service = _.keys(user.services)[0];
        var email = user.services[service].email;
        if (!email) {
            if (user.emails) {
                email = user.emails.address;
            }
        }
        if (!email) {
            email = options.email;
        }
        if (!email) {
            // if email is not set, there is no way to link it with other accounts
            return user;
        }

        // see if any existing user has this email address, otherwise create new
        var existingUser = Meteor.users.findOne({'emails.address': email});
        if (!existingUser) {
            // check for email also in other services
            var existingGitHubUser = Meteor.users.findOne({'services.github.email': email});
            var existingGoogleUser = Meteor.users.findOne({'services.google.email': email});
            var existingTwitterUser = Meteor.users.findOne({'services.twitter.email': email});
            var existingFacebookUser = Meteor.users.findOne({'services.facebook.email': email});
            var doesntExist = !existingGitHubUser && !existingGoogleUser && !existingTwitterUser && !existingFacebookUser;
            if (doesntExist) {
                // return the user as it came, because there he doesn't exist in the DB yet
                return user;
            } else {
                existingUser = existingGitHubUser || existingGoogleUser || existingTwitterUser || existingFacebookUser;
                if (existingUser) {
                    if (user.emails) {
                        // user is signing in by email, we need to set it to the existing user
                        existingUser.emails = user.emails;
                    }
                }
            }
        }

        // precaution, these will exist from accounts-password if used
        if (!existingUser.services) {
            existingUser.services = { resume: { loginTokens: [] }};
        }

        // copy accross new service info
        existingUser.services[service] = user.services[service];
        existingUser.services.resume.loginTokens.push(
            user.services.resume.loginTokens[0]
        );

        // even worse hackery
        Meteor.users.remove({_id: existingUser._id}); // remove existing record
        return existingUser;                  // record is re-inserted
    }
});
于 2014-10-05T12:34:47.213 に答える