【问题标题】:Why does this Firebase Database security rule with && and || not work为什么这个 Firebase 数据库安全规则带有 && 和 ||不行
【发布时间】:2017-07-03 04:58:09
【问题描述】:

在我使用 Firebase 创建的 iOS 应用中,每个用户都有一个唯一的用户名,该用户名是在他们使用电子邮件和密码注册后创建的。

因此,如果一个用户的电子邮件是 test5@gmail.com,然后必须创建一个不在用户名数据库中的唯一用户名,那么数据库的 sn-p 将如下所示:

    "usernames" : {
        "test" : "r6KPesUr1qORfIJke07SloZHeNW2",
        "test1" : "jSMSkY9rHtdNkXoLrsFmCAXdY9n2",
        "test7" : "jnFhJbgCjZeJFx0hspObqoskQej2",
        "test8" : "HtnULzU0lnZKYva2M2Wepl6N8wE3"
    },

    "users" : {
        "HtnULzU0lnZKYva2M2Wepl6N8wE3" : {
            "email" : "test8@gmail.com",
            "username" : "test8"
        },
        "boX6rtJ98haWVxNoXfSq21maCVU2" : {
            "email" : "test5@gmail.com"
        },
        "jSMSkY9rHtdNkXoLrsFmCAXdY9n2" : {
            "email" : "Test1@gmail.com",
            "username" : "test1"
        },
        "jnFhJbgCjZeJFx0hspObqoskQej2" : {
            "email" : "test7@gmail.com",
            "username" : "test7"
        },
        "r6KPesUr1qORfIJke07SloZHeNW2" : {
            "email" : "test6@gmail.com",
            "username" : "test"
        }
    }

我制定了以下安全规则,以确保用户完成注册后用户名是唯一的。

    // USERNAMES
    "usernames": {
        ".read": "auth.uid != null",
        ".write": "auth.uid != null",
        "$username": {
            ".validate": "(!root.child('usernames').hasChild($username.toLowerCase()) && newData.val() == auth.uid && 
                          root.child('users').hasChild(auth.uid)) &&

                          (root.child('users/'+auth.uid+'/username').val().toLowerCase() == $username || 
                          !root.child('users/'+auth.uid+'/username').exists())"                 
        }                                   
    }

对于验证规则,我希望这三个语句必须具备

   (!root.child('usernames').hasChild($username.toLowerCase()) && 
     newData.val() == auth.uid && 
     root.child('users').hasChild(auth.uid))

这两个陈述中的一个必须是正确的

   "(root.child('users/'+auth.uid+'/username').val().toLowerCase() == $username || 
    (!root.child('users/'+auth.uid+'/username').exists()"

因此,如果用户想使用 test5 作为具有以下 json 的用户名进行注册,那么由于 OR 语句的第一部分,它将不适用于我当前的安全规则。

     "users": {
         "boX6rtJ98haWVxNoXfSq21maCVU2": {
              "username": "test5"
          }
     }

我做错了什么?

【问题讨论】:

  • 解析规则相当困难。您能否编辑您的问题以包含可能会被此验证规则拒绝但您希望允许的最少代码?
  • @FrankvanPuffelen 确定。我已经添加了数据库的外观以及随后无法写入的 json,以使用 test5@gmail.com 的电子邮件为用户创建唯一的用户名
  • 好的。我试着弄清楚你的用例。但是从如此复杂的规则中理解起来很棘手,因此我分离了一个(以及两个)特定用例并专注于它。
  • @FrankvanPuffelen 你绝对又搞定了。那是我的确切用例。不知道还能说什么,但非常感谢。 Firebase 很棒
  • 很高兴听到我猜对了爱德华。最近有很多安全规则问题,所以我的头越来越疼。 :-) 在 Firebase 上玩得开心!

标签: firebase firebase-realtime-database firebase-security


【解决方案1】:

您似乎希望用户声明用户名发生两件事:

  1. 一个节点用他们的用户名写在/users/$uid/username
  2. /usernames/$username 下写入一个节点及其UID

您现在编写的 JSON sn-p 仅包含 #1。它不包含任何关于在/usernames 下写入用户名的内容。因此该规则将拒绝它,因为您正在验证用户名必须存在并为该用户声明。

您可能想要验证 #1 和 #2 是否同时发生,这将是一个多位置更新,例如:

 "users/boX6rtJ98haWVxNoXfSq21maCVU2/username": "test5",
 "usernames/test5": "boX6rtJ98haWVxNoXfSq21maCVU2"

你的规则是:

"usernames": {
  "$username": {
    ".validate": "!data.exists() && 
      newData.exists() &&
      newData.parent().parent().child('users').child(auth.uid).child('username').val() === $username"
    }                                   
}
"users": {
  "$uid": {
    "username": {
      ".validate": "!data.exists() && 
        newData.exists() &&
        newData.parent().parent().parent().child('usernames').child(newData.val()).val() === $uid"
    }
  }
}

我删除了关于小写的部分,因为在您的代码中更容易修复它并且只存储小写用户名。

【讨论】:

  • 我认为您需要从 newData() 中删除“用户”和“用户名”中的结束规则的括号
  • 我不确定我理解你的意思。不过,请随时提出修改建议。
猜你喜欢
  • 2016-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-18
  • 2017-04-16
  • 1970-01-01
  • 2021-07-28
  • 2021-07-14
相关资源
最近更新 更多