Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Firebase 使用安全规则限制子/字段访问_Firebase_Firebase Realtime Database - Fatal编程技术网

Firebase 使用安全规则限制子/字段访问

Firebase 使用安全规则限制子/字段访问,firebase,firebase-realtime-database,Firebase,Firebase Realtime Database,我正在编写一个应用程序,允许用户提交提名,提名在显示给其他用户之前经过审核。这需要一些限制,我迄今为止在安全规则方面没有成功实施: 隐藏任何尚未批准的提名 对提交隐藏私人字段(电话、批准状态、创建日期等) 我目前的规则如下: { "rules": { "nominations": { ".read": true, "$nominationId": { ".read": "data.child

我正在编写一个应用程序,允许用户提交提名,提名在显示给其他用户之前经过审核。这需要一些限制,我迄今为止在安全规则方面没有成功实施:

  • 隐藏任何尚未批准的提名
  • 对提交隐藏私人字段(电话、批准状态、创建日期等)
  • 我目前的规则如下:

    {
        "rules": {
            "nominations": {
                ".read": true,
    
                "$nominationId": {
                    ".read": "data.child('state').val() == 'approved' || auth != null", // Only read approved nominations if not authenticated
                    ".write": "!data.exists()", // Only allow new nominations to be created
    
                    "phone": {
                        ".read": "auth != null" // Only allow authenticated users to read phone number
                    },
    
                    "state": {
                        ".read": "auth != null", // Only allow authenticated users to read approval state
                        ".write": "auth != null" // Only allow authenticated users to change state
                    }
                }
            }
        }
    }
    
    my-firebase
        |
        `- nominations
            |
            `- entries
            |   |
            |   `- private
            |   `- public
            |
            `- status
                |
                `- pending
                `- approved
                `- rejected
    
    子规则(例如,
    $提名
    )不会阻止从父项读取整个子项。如果我听了
    child\u添加了
    ,它会愉快地返回所有孩子和他们的所有数据,即使有上述安全规则

    我目前的解决方案是保留一个名为
    approved
    的单独节点,并在有人批准或拒绝提名时在列表之间移动数据,但这似乎是一种非常糟糕的方法

    更新

    下面是我的精彩评论,我用最少的努力重新实现了最初的想法

    新的数据结构如下:

    {
        "rules": {
            "nominations": {
                ".read": true,
    
                "$nominationId": {
                    ".read": "data.child('state').val() == 'approved' || auth != null", // Only read approved nominations if not authenticated
                    ".write": "!data.exists()", // Only allow new nominations to be created
    
                    "phone": {
                        ".read": "auth != null" // Only allow authenticated users to read phone number
                    },
    
                    "state": {
                        ".read": "auth != null", // Only allow authenticated users to read approval state
                        ".write": "auth != null" // Only allow authenticated users to change state
                    }
                }
            }
        }
    }
    
    my-firebase
        |
        `- nominations
            |
            `- entries
            |   |
            |   `- private
            |   `- public
            |
            `- status
                |
                `- pending
                `- approved
                `- rejected
    
    每个提名都存储在
    条目
    下,私人数据如电话号码、电子邮件等。私人数据存储在
    私人
    下,公开数据存储在
    公共

    更新后的规则如下:

    {
        "rules": {
            "nominations": {
                ".read": true,
    
                "$nominationId": {
                    ".read": "data.child('state').val() == 'approved' || auth != null", // Only read approved nominations if not authenticated
                    ".write": "!data.exists()", // Only allow new nominations to be created
    
                    "phone": {
                        ".read": "auth != null" // Only allow authenticated users to read phone number
                    },
    
                    "state": {
                        ".read": "auth != null", // Only allow authenticated users to read approval state
                        ".write": "auth != null" // Only allow authenticated users to change state
                    }
                }
            }
        }
    }
    
    my-firebase
        |
        `- nominations
            |
            `- entries
            |   |
            |   `- private
            |   `- public
            |
            `- status
                |
                `- pending
                `- approved
                `- rejected
    
    {
    “规则”:{
    “提名”:{
    “条目”:{
    “$id”:{
    “.write”:“!data.exists()”,
    “公众”:{
    “.read”:正确,
    },
    “私人”:{
    .read:“auth!=null”
    }
    }
    },
    “地位”:{
    “待定”:{
    “.read”:“auth!=null”,
    “$id”:{
    .write:“root.child('namignations/entries').child($id.exists()&&(auth!=null | | newData.val()=true)”
    }
    },
    “批准”:{
    “.read”:正确,
    “$id”:{
    .write:“root.child('提名/条目').child($id.exists()&&auth!=null”
    }
    },
    “拒绝”:{
    “.read”:“auth!=null”,
    “$id”:{
    .write:“root.child('提名/条目').child($id.exists()&&auth!=null”
    }
    }
    }
    }
    }
    }
    
    以及JavaScript实现:

    var db=new Firebase('https://my.firebaseio.com')
    变量提名=db.child('提名')
    var entries=namignations.child('entries')
    变量状态=提名。子项('状态')
    var pending=status.child('pending')
    var approved=状态。子级(“approved”)
    var rejected=status.child('rejected')
    //通过表单输入创建提名(未显示)
    var createNamement=函数(){
    风险值数据={
    公众:{
    名称:“Foo”,
    年龄:20
    },
    私人:{
    createdAt:new Date().getTime(),
    电话:123456
    }
    }
    var提名=条目。推送()
    提名.setWithPriority(data,data.private.createdAt)
    挂起.child(提名.name()).set(true)
    }
    //检索当前提名状态
    var getStatus=函数(id,回调){
    已批准.child(id).once('value',函数(快照){
    if(snapshot.val()){
    回调(id为“已批准”)
    }否则{
    拒绝.child(id).once('value',函数(快照){
    回调(id,snapshot.val()?“已拒绝”:“挂起”)
    })
    }
    })
    }
    //更改提名状态
    var changeStatus=函数(id、from、to){
    status.child(from).child(id).remove()
    status.child(to).child(id).set(true)
    }
    
    我正在努力解决的唯一一个实现部分是处理状态更改,我当前的方法肯定可以改进:

    \每个([待定、批准、拒绝])功能(状态){
    状态.on('child_added',函数(快照){
    $('#'+snapshot.name()).removeClass('pending approved rejected').addClass(status.name())
    })
    })
    

    我计划在
    提名/状态
    上使用
    child\u changed
    ,但我无法让它可靠地工作。

    如果我完全摸索安全规则的工作方式(我只是自己学习),那么当任何一条规则允许访问时,访问都被授予。因此,其内容如下:

    {
        "rules": {
            "nominations": {
                ".read": true,
    
                "$nominationId": {
                    ".read": "data.child('state').val() == 'approved' || auth != null", // Only read approved nominations if not authenticated
                    ".write": "!data.exists()", // Only allow new nominations to be created
    
                    "phone": {
                        ".read": "auth != null" // Only allow authenticated users to read phone number
                    },
    
                    "state": {
                        ".read": "auth != null", // Only allow authenticated users to read approval state
                        ".write": "auth != null" // Only allow authenticated users to change state
                    }
                }
            }
        }
    }
    
    my-firebase
        |
        `- nominations
            |
            `- entries
            |   |
            |   `- private
            |   `- public
            |
            `- status
                |
                `- pending
                `- approved
                `- rejected
    
    • 提名“.read”:正确,授予访问权限
    • 其他规则:不要阅读
    此外,如果删除了该规则,
    $namignionid
    ”.read“在记录被批准的情况下授予访问权限;因此,
    手机中的
    .read
    状态
    一旦获得批准就变得多余

    将其分解为
    public/
    private/
    子项可能是最简单的,如下所示:

    nominations/unapproved/          # only visible to logged in users
    nominations/approved/            # visible to anyone (move record here after approval)
    nominations/approved/public/     # things everyone can see
    nominations/approved/restricted/ # things like phone number, which are restricted
    
    更新


    再想一想,我想你仍然会遇到一个问题,那就是将
    approved/
    公开,这将允许你列出记录,并将
    approved/restricted/
    私有化。在这个用例中,受限制的数据可能也需要它自己的路径。

    加藤是对的。重要的是要了解安全规则从不过滤数据。对于任何位置,您都可以读取所有数据(包括其子项),或者不读取任何数据。因此,在您的规则中,“提名”下的“.read”:true否定了所有其他规则

    所以我推荐的方法是有3个列表。一个包含提名数据,一个包含核准提名列表,一个包含待提名列表

    你的规则可以是这样的:

    {
      "rules": {
        // The actual nominations.  Each will be stored with a unique ID.
        "nominations": {
          "$id": {
            ".write": "!data.exists()", // anybody can create new nominations, but not overwrite existing ones.
            "public_data": {
              ".read": true // everybody can read the public data.
            },
            "phone": {
              ".read": "auth != null", // only authenticated users can read the phone number.
            }
          }
        },
        "approved_list": {
          ".read": true, // everybody can read the approved nominations list.
          "$id": {
            // Authenticated users can add the id of a nomination to the approved list 
            // by creating a child with the nomination id as the name and true as the value.
            ".write": "auth != null && root.child('nominations').child($id).exists() && newData.val() == true"
          }
        },
        "pending_list": {
          ".read": "auth != null", // Only authenticated users can read the pending list.
          "$id": {
            // Any user can add a nomination to the pending list, to be moderated by
            // an authenticated user (who can then delete it from this list).
            ".write": "root.child('nominations').child($id).exists() && (newData.val() == true || auth != null)"
          }
        }
      }
    }
    
    未经身份验证的用户可以添加具有以下内容的新提名:

    var id = ref.child('nominations').push({ public_data: "whatever", phone: "555-1234" });
    ref.child('pending_list').child(id).set(true);
    
    认证用户公司