在 Firebase 中通过电子邮件查找 UID

Posted

技术标签:

【中文标题】在 Firebase 中通过电子邮件查找 UID【英文标题】:Finding an UID by email in Firebase 【发布时间】:2016-06-26 16:28:46 【问题描述】:

我首先尝试像这样实例化数据库中的每个用户:

emails : 
    email: "jerry@gmail.com" 
        uid: "x"
    

我很快发现我无法存储电子邮件,因为它有 @.。我原本打算像这样进行用户查找:

func userLookUpByEmail (email: String) -> String 
    var userID: String = "nil"

    ref.queryOrderedByChild("emails").queryEqualToValue(email).observeSingleEventOfType(.ChildAdded, withBlock:  snapshot in
            if snapshot.value != nil 
                print(snapshot.value)
                userID = snapshot.value as! String
            
            else 
                print ("user not found")
                userID = "nil"
            
    )
    return userID

但是,我意识到这行不通。通过提供电子邮件接收 UID 的有效方法是什么?

【问题讨论】:

您的数据结构不是有效的 JSON。请使用有效的 JSON 更新您的问题。 这样的东西似乎是最简单的数据结构来做你正在寻找的东西:***.com/questions/37897656/… 【参考方案1】:

回答您的问题,因为您不能将电子邮件作为子键,您可以以另一种方式,将 uid 设置为键,将电子邮件设置为子键

emails : 
    uid: 
        email: "jerry@gmail.com"
    

然后你的代码会发生一点变化。

func userLookUpByEmail (email: String, completionHandler: (result: String) -> Void) 
    var userID: String = "nil"
    ref.child("emails").queryOrderedByChild("email").queryEqualToValue(email).observeSingleEventOfType(.ChildAdded, withBlock:  snapshot in
                if snapshot.value != nil 
                    print(snapshot.key)
                    userID = snapshot.key as! String
                
                else 
                    print ("user not found")
                    userID = "nil"
                
                completionHandler(userID)
        )
 

致电userLookUpByEmail:

userLookUpByEmail(email) 
    (result: String) in
    print("\(result)")

另一方面,我想知道为什么你的数据库中有一个 emails 分支,因为你可以有一个 users 分支(如果你还没有的话)并在那里存储任何用户数据,包括电子邮件。这将使您的数据结构更加干净和可靠。再说一次,我在这里想知道,因为我不完全了解您的需求。

users : 
    uid: 
        email: "jerry@gmail.com",
        name: "Jerry Maguire",
        ...
    

【讨论】:

我收到错误 Using an unspecified index. Consider adding ".indexOn": "email" at /emails to your security rules for better performance。我的规则应该看起来像 "rules": ".read": "auth != null", ".write": "auth != null" "/emails" ".indexOn" : "email" 吗? @user5812721 这不是错误。您的代码应该在没有它的情况下工作,因为它只是为了内部 firebase 性能。您正在寻找的规则是: "rules": ".read": "auth != null", ".write": "auth != null", "emails": ".indexOn" : "email" 在我添加规则之前会找到快照键,但现在它总是为零。同样在我的) 之后,我写了print(userid) 但它也出现了零,这就是为什么我认为这是一个错误。在我添加规则之前,我在第一个 if 语句中打印了快照键,它总是正确的。 @user5812721 您通过了身份验证吗?此外,如果您尝试在 ) 之后打印用户 ID,它将失败,因为您是从异步回调函数中调用它。如果你想在我的代码中找到的 return 语句之前打印它。 @user5812721 我的错,你根本无法返回。在这种情况下,您应该使用completionHandler。我已经用正确的信息编辑了这个问题。无论如何,很高兴你做到了。 :)【参考方案2】:

首先,您不能在数据库中存储某些字符是正确的。根据 Firebase 文档,(https://firebase.google.com/docs/database/ios/structure-data)

如果您创建自己的密钥,它们必须是 UTF-8 编码的,最多可以是 768 个字节,并且不能包含 .、$、#、[、]、/ 或 ASCII 控制字符 0-31 或 127 .

但是,正如您所见,“@”符号不是其中之一。至于点,您可以使用一个函数将点替换为另一个字符。例如, ”•”。这是一个例子:

func createNewEmail(oldEmail: String) -> String
    return oldEmail.componentsSeparatedByString(".").joinWithSeparator("•")

它的作用是将电子邮件拆分为“email@example”和“com”的数组。然后,它用新字符重新加入它们,创建“email@example•com”

如果您曾经需要旧电子邮件,您可以反过来做同样的事情。

func getOldEmail(newEmail: String) -> String
    return newEmail.componentsSeparatedByString("•").joinWithSeparator(".")

然后你可以像这样格式化你的树

emails:
    email@example•com: UID123456789

最后,对于你原来的问题,函数可以这样写

func userLookUpByEmail (email: String) -> String 
    let newEmail = createNewEmail(email)
    var userID: String = "nil"

    ref.child("emails").child(newEmail).observeSingleEventOfType(.ChildAdded, withBlock:  snapshot in
            if snapshot.value != nil 
                print(snapshot.value)
                userID = snapshot.value as! String
            
            else 
                print ("user not found")
                userID = "nil"
            
    )
    return userID

但是,您可能每次都会得到“nil”。这是因为observeSingleEventOfType 是一个闭包。这意味着它在您的应用程序的后台运行。因此,用户 ID 可能会在闭包内更改之前返回。您可能希望在闭包内运行基于 userID 的任何代码,而不是返回 userID。例如,不要这样做:

func userLookUpByEmail (email: String) -> String 
    let newEmail = createNewEmail(email)
    var userID: String = "nil"

    ref.child("emails").child(newEmail).observeSingleEventOfType(.ChildAdded, withBlock:  snapshot in
            if snapshot.value != nil 
                print(snapshot.value)
                userID = snapshot.value as! String
            
            else 
                print ("user not found")
                userID = "nil"
            
    )
    return userID


doSomethingWith(lookUserUpByEmail(email@example.com))

你可以这样做:

func userLookUpByEmail (email: String)
    let newEmail = createNewEmail(email)
    var userID: String = "nil"

    ref.child("emails").child(newEmail).observeSingleEventOfType(.ChildAdded, withBlock:  snapshot in
            if snapshot.value != nil 
                print(snapshot.value)
                userID = snapshot.value as! String
                doSomethingWith(userID)
            
            else 
                print ("user not found")
                userID = "nil"
                doSomethingWith(userID)
            
    )

【讨论】:

我将它保存到一个名为temp_uid 的类的变量中,然后在我调用userLookUpByEmail 之后将该变量保存到user2uid,但temp_uid 仍然没有及时收到正确的值. @user5812721 你基本上不能把任何东西放在闭包之外。在大多数情况下,您放在括号外的任何内容都无法正常工作。试图打败时钟是行不通的。你需要把你想用snapshot做的everything放在闭包中。如果您想对这些值做一些事情,请创建一个函数,然后将其放入其中。比如我放doSomethingWith(userID)的地方,你想放什么就放什么。 澄清一下......您可以将数据存储在闭包/块之外,但在快照在块内有效之前,您不应对该数据采取行动。因此,例如,您可以在块之外拥有一个类级别数组 self.myArray(一个 tableview 数据源)。您将从块内的快照中填充该数组,并告诉您的 tableview 从块内重新加载自己,在填充数组后,再次在块内。

以上是关于在 Firebase 中通过电子邮件查找 UID的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Flutter 应用程序中删除 firebase 用户? [复制]

如何查找 Firebase 文档字段并删除文档

如何根据数据库用户 id(不是 uid)设置 firebase 规则

在 Firestore 中通过 docId 批量设置文档字段时遇到问题

如何从 Flutter 中的 Firebase 的 UID 获取任何用户的电子邮件? [复制]

如何使用 Vue.js Firebase UID 删除用户