Meteor.loginWithPassword 不适用于带有 @ 字符的用户名

Posted

技术标签:

【中文标题】Meteor.loginWithPassword 不适用于带有 @ 字符的用户名【英文标题】:Meteor.loginWithPassword not working with username with @ character 【发布时间】:2021-04-12 08:25:52 【问题描述】:

我在数据库中有一个具有以下凭据的用户:


    "_id": "zTHv8yqPSm3pmi4So",
    "emails": ["address": "someemail@example.com", "verified": true],
    "services" : 
        "password" : 
            "bcrypt" : "$2b$10$L6HXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo1IjZEx6.PBxfOeQHqS."
        ,
        "resume" : 
            "loginTokens" : [ ]
        
    ,
    "username": "some@username",
    "profile": 
        "firstName": "Example",
        "lastName": "User",
    

当我尝试使用用户名登录用户时,它说找不到用户:

Meteor.loginWithPassword("some@username", "123456", function(error) 
    console.log(error.reason); 
);

它适用于电子邮件,但不适用于用户名。

我希望灵活地使用电子邮件或用户名登录用户

【问题讨论】:

您在数据库中的用户记录没有密码。看起来很不对劲。它缺少一个带有加密密码的服务字段。我认为更好的问题是为什么这对电子邮件有效?也许你发现了流星中的一个错误,因为根据你显示的记录,应该不允许任何人登录。 您实际上可以创建没有密码的用户,因此需要用户首先通过确认电子邮件或密码重置电子邮件设置密码。这在Accounts docs 中有很好的记录 您的数据库有"username": "some@username",,但您的登录尝试使用的是someusername。这是问题还是这只是您问题中的错字? 打错字了,抱歉 【参考方案1】:

API Meteor.loginWithPassword 实际上将“选择器”作为第一个参数:

https://docs.meteor.com/api/accounts.html#Meteor-loginWithPassword

Meteor.loginWithPassword(selector, password, [callback])

论据

selector 对象或字符串

字符串被解释为用户名或电子邮件;或具有单个键的对象:emailusernameid

在您的情况下,您使用字符串形式,并让 Meteor 尝试猜测它是用户名还是电子邮件。

但由于您的用户名包含“@”字符,这会误导 Meteor 将其解释为电子邮件:

https://github.com/meteor/meteor/blob/release/METEOR%401.12.1/packages/accounts-password/password_client.js#L33-L38

Meteor.loginWithPassword = (selector, password, callback) => 
  if (typeof selector === 'string')
    if (!selector.includes('@'))
      selector = username: selector;
    else
      selector = email: selector;

这就是为什么当您尝试使用电子邮件时它可以正常工作,但对于包含“@”的用户名却失败了。

简单的解决方案是明确告诉 Meteor 你的目标是用户名(而不是电子邮件,尽管有“@”):

Meteor.loginWithPassword(
        username: "some@username"
    ,
    "123456",
    function(error) 
        console.log(error.reason); 
    
);

现在,如果我想进一步猜测您的目标,您希望您的用户能够提供他们的电子邮件或用户名作为登录标识符,而无需明确说明是哪一个? (就像一种“全能”登录 id 输入)

在这种情况下,很遗憾,您将不得不检测自己是电子邮件还是用户名。如果后者确实遵循“some@username”之类的模式,则可以尝试检测域不完整(无扩展名)。

但如果您的任何用户确实注册了一个看起来像电子邮件的用户名(例如“some@user.name”),那么您可能无法区分它们。

更糟糕的是,一些用户可能选择的用户名正是另一个用户的电子邮件地址!那么,如何判断是哪一个正在尝试登录呢?

恕我直言,这对于略微改进的用户体验来说会变得很麻烦。要么阻止包含“@”的用户名,即强制执行一个规则,使您能够区分,或者提供一种方法让用户在不明确时明确判断它是电子邮件还是用户名(例如,它可以是一些无线电来判断哪个输入它;当登录 ID 明确时,它仍然可以包含“自动”模式)。

顺便说一句,我们还可以想象执行 2 步登录尝试:首先按原样,然后如果用户名包含“@”,则显式地作为用户名,如上所述。但是我们仍然可能陷入上述最坏的情况......

【讨论】:

以上是关于Meteor.loginWithPassword 不适用于带有 @ 字符的用户名的主要内容,如果未能解决你的问题,请参考以下文章