为什么此Firebase数据库安全规则带有&&和||不行

时间:2017-02-14 18:51:55

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

在我使用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()"

因此,如果用户希望使用以下json注册 test5 作为用户名,那么由于OR语句的第一部分,它将无法使用我当前的安全规则。

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

我做错了什么?

1 个答案:

答案 0 :(得分:1)

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

  1. 一个节点写在/users/$uid/username下,用户名为
  2. /usernames/$username下使用UID
  3. 编写节点

    您现在编写的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"
        }
      }
    }
    

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