【问题标题】:Listener at /users failed: permission_denied/users 的侦听器失败:permission_denied
【发布时间】:2017-12-26 07:02:15
【问题描述】:

我有一个使用 Firebase 的注册流程。当我检查数据库中是否已经存在电子邮件时,如下所示:

refUsers.queryOrdered(byChild: "email").queryEqual(toValue: emailText).observeSingleEvent(of: .value, with: { snapshot in

      if (snapshot.value is NSNull) {
            print("Unique email")

            // Move to Password View.
            let passwordViewController = self.storyboard?.instantiateViewController(withIdentifier: "PasswordViewController") as! PasswordViewController

            self.navigationController?.present(passwordViewController, animated: true, completion: nil)

            // Pass the emailText to the last View of the flow.
            self.singleton.sharedInstance.emailText = emailText!

      }
      else {
            print("Duplicate email")
      }  
})

问题是,我没有权限查看数据库中的/users,因为我的规则是:

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null"
  }
}

我知道我可以使用 Auth.auth().createUser 查找电子邮件是否重复,但我在注册流程中检查的不仅仅是电子邮件。我也对唯一用户名使用相同的方法。我怎样才能做到这一点?

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database firebase-authentication


    【解决方案1】:

    如您所见,这不是最好的方法。您不应该手动检查电子邮件是否已经存在 - Firebase 可以在用户注册时为您执行此操作,您为什么不想使用它?

    您需要的是一种不同的方法。我现在能想到两种方法:

    第一:

    您可以向 Firebase 添加新规则,例如:

    {
        "rules": {
        "usernames": {
          ".read": true,
          ".write": "auth != null"
        },
        "emails": {
          ".read": true,
          ".write": "auth != null"
        }
      }
    }
    

    您在这里所做的是创建一个名为usernames 的新节点,每个用户都可以访问和阅读该节点。 在这里,您应该保存注册用户拥有的所有用户名的副本,并在注册时检查用户用户名是否已经在此节点内。

    第二种方式:

    您可以稍微修改一下您的注册流程,让用户无需用户名即可注册。创建帐户后,您让他们设置用户名。有了一个很好的流程,它看起来就像同一个注册表单。

    更新 使用上述规则,用户无需注册即可阅读emailsusernames。这样您就可以获取数据并比较电子邮件或用户名是否已被使用。

    只需确保在用户注册时将他的电子邮件和用户名插入这两个节点即可。

    【讨论】:

    • 如果我也为电子邮件添加相同的规则怎么办?那会是一个好方法吗?我不希望 Firebase 为我这样做,因为这不会让我建立一个好的注册流程。
    • @waseefakhtar 我已经更新了我的答案。稍微修改了代码,在 UPDATE 文本之后写。
    • 我明白这一点。感谢您的宝贵时间。
    【解决方案2】:

    虽然@ZassX 的回答对我有所帮助,但对于像我这样困惑的人来说,我已经了解了一个好的方法。

    最好的方法是使用"auth != null" 规则保护/users 中的用户数据安全。仅向每个人显示用户的元数据,其中仅包括每个用户的电子邮件和密码。例如:

    数据库

    {
        “metaData”: { 
            uid: { 
                “email”: …,
                “password”: …
            }
        },
        “users”: { 
            uid: { 
                “email”: …,
                “password”: …
                // other information
            }
        }
     }
    

    安全

    {
        "rules": {
            “metaData”: { 
                “.read”: true,
                “.write”: “auth !== null”
            },
            “users”: { 
                “.read”: “auth !== null”,
                “.write”: “auth !== null”
            }
        }   
    }
    

    现在可以匹配元数据中的信息,而无需先对用户进行身份验证。当然,随着您添加更多安全性,这可能会变得更加复杂,但为了便于理解,就是这样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-15
      • 2020-10-29
      • 2015-02-21
      • 1970-01-01
      • 2011-02-11
      • 2016-05-04
      相关资源
      最近更新 更多