为什么Firebase数据库安全规则与&&;而且| |不工作

为什么Firebase数据库安全规则与&&;而且| |不工作,firebase,firebase-realtime-database,firebase-security,Firebase,Firebase Realtime Database,Firebase Security,在我使用Firebase创建的iOS应用程序中,每个用户都有一个唯一的用户名,该用户名是在他们使用电子邮件和密码注册后创建的 因此,如果用户的电子邮件为test5@gmail.com已注册,然后必须创建用户名数据库中没有的唯一用户名数据库的一段代码如下: "usernames" : { "test" : "r6KPesUr1qORfIJke07SloZHeNW2", "test1" : "jSMSkY9rHtdNkXoLrsFmCAXdY9n2",

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

因此,如果用户的电子邮件为test5@gmail.com已注册,然后必须创建用户名数据库中没有的唯一用户名数据库的一段代码如下:

    "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"
          }
     }

我做错了什么?

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

  • 节点写在
    /users/$uid/username
    下,并带有其用户名
  • 节点用UID写在
    /usernames/$username
  • 您现在编写的JSON代码段只包含#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"
        }
      }
    }
    

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

    解析规则非常困难。您是否可以编辑您的问题,以包含此验证规则将拒绝但您希望允许的最小代码?@frankvanpoffelen当然可以。我已经添加了数据库的外观,以及随后无法编写的json,以便为电子邮件为的用户创建唯一的用户名test5@gmail.comOK. 我试着找出你的用例。但要从如此复杂的规则中理解它是很难的,所以我隔离了一个(两个)特定的用例,并将重点放在它上。@FrankvanPuffelen你又一次完全搞定了它。这正是我的用例。不知道还能说什么,但非常感谢。听说我猜对了,真是太好了,爱德华。最近有很多关于安全规则的问题,所以我的头越来越痛。:-)祝你在Firebase上玩得开心!我认为您需要删除newData()中“users”和“usernames”中的结束规则的括号。我不确定我是否理解您的意思。尽管如此,请随意建议编辑。