在 Meteor 中存储未决用户密码的安全方法

Secure way to store pending user's password in Meteor

对于我的 Meteor 应用程序,我希望有以下注册过程:

  1. 用户注册用户名、电子邮件和密码(他还不能登录。)
  2. 已发送确认邮件 [Accounts.sendEnrollmentEmail]
  3. 用户确认电子邮件 [Accounts.onEnrollmentLink]
  4. 用户已创建。 [Accounts.createUser] (他可以登录了。)

为了实现这一点,我觉得我必须将 纯文本 密码存储在 table 临时用户(步骤 1)中,以便稍后创建实际用户(第 3 步)。显然这是一个糟糕的想法。

我当然可以只要求输入第 3 步的密码并立即创建用户 - 但这不是我想要实现的行为。

因此:是否有适当的方法来安全地存储密码以便稍后将其传递给用户创建?或者有没有办法创建不可登录的用户?

当您使用内置方法创建用户时,Meteor 提供了保存密码存储所需的一切,因此您无需自己做太多事情。所以你应该从一开始就使用这些方法(你的第 1 步:Accounts.createUser,第 2 步:Accounts.sendVerificationEmail,第 3 步:Accounts.verifyEmail,第 4 步不再是必需的)。

现在要到达您想去的地方,您可以使用 David Weldon 建议的方法,但在服务器端使用 Accounts.validateLoginAttempt。这更容易一些,首先不允许登录。

例如,您可以在服务器端使用此代码:

Accounts.validateLoginAttempt(function(loginAttempt){
    if (!loginAttempt.allowed) {
        // Only tell the user that something went wrong but not what to enhance security
        throw new Meteor.Error(901, 'Your login credentials are wrong. Try again.');
    } else {

        // In some cases this method isn't invoked with a correct user object...
        if (!loginAttempt.user) {
            throw new Meteor.Error(902, 'No valid user object. Make sure to validate your email address first.');
        }

        // If email verification is required check if the user has a valid email address and don't allow the login if he has none
        if (!loginAttempt.user.emails[0].verified) {
            throw new Meteor.Error(902, 'Your email address has to be verified first.');
        }

        // We have a correct login!
        return true;
    }
});

现在在客户端,您可以使用这样的逻辑进行登录

Meteor.loginWithPassword(email, password, function(callback) {
    if (callback === undefined) { 
        // Your login logic
    } else if (callback.error == 902) {
        // Your "not verfied" logic
    } else {
        // Your other login errors logic
    }
}

请注意,您可能还需要稍微调整注册过程,因为 Meteor 默认情况下会尝试在注册后直接登录用户,但这将不再可能。 另请注意,您可以使用 Accounts.validateLoginAttempt 不止于此。例如,您还可以在此处实现一个逻辑,只允许来自同一 IP 的一定数量的错误登录尝试。

我们根据帐户包在我们的应用中使用了稍微不同的模式

  1. 用户注册
  2. 用户正常登录

出主站模板条件内容与

<template name="main">
  {{#if currentUser}}
    {{#if verified }}
      ...
    {{else}}
      Notice to user to look for their verification email
    {{/if}}
  {{/if}}
</template>

基于辅助函数

 Template.main.helpers({
   verified: function() { return Meteor.user().emails[0].verified; }
 });

这满足了用户在通过验证之前不能做任何事情的要求,但仍以简单安全的方式使用帐户包。

我也可以看到使用 iron:router 采取相关方法。