代码之家  ›  专栏  ›  技术社区  ›  flipcode

如果节点密钥与用户id不同,则拒绝创建子节点。Firebase规则

  •  1
  • flipcode  · 技术社区  · 7 年前

    假设我的数据库结构如下:

    /
        favorites
            ownerid_1
                favorite1_id
                    title
                    link
                favorite2_id
                    title
                    link
            ownerid_2
                etc
    

    我可以轻松地将Firebase权限设置为以下内容:

    {
        "rules": {
            "favorites": {
                "$owner_id": {
                    ".read": "root.child('favorites').child($owner_id) == auth.uid",
                    ".write": "root.child('favorites').child($owner_id) == auth.uid",
                }
            }
        }
    }
    

    但是,收藏夹是可选的,用户可以决定何时创建第一个收藏夹。用户的“$user\u id”数据结构在存在之前不存在。

    我正在努力解决如何在/收藏夹中加入验证规则,以允许用户仅在密钥与其用户id相同时创建新的子节点。

    i、 e.ownerid\u 1无法创建ownerid\u 2节点。

    我尝试了以下操作,但模拟器没有指定特定的行而失败:

    {
        "rules": {
            "favorites": {
                ".validate": "newData.hasChild(auth.uid)",
    
                "$owner_id": {
                    ".read": "root.child('favorites').child($owner_id) == auth.uid",
                    ".write": "root.child('favorites').child($owner_id) == auth.uid",
                }
            }
        }
    }
    

    更新#1 以下是规则中未指定任何行的日志:

    Type    write
    Location    /favorites/
    Data    { "JhDa8owfAkTRR5qMbuvAgEyUHYL2": { "favid1": { "title": "google", "link": "www.google.com" } } }
    Auth    { "provider": "google", "uid": "JhDa8owfAkTRR5qMbuvAgEyUHYL2" }
    Admin   false
    

    更新#2

    我尝试了以下方法:

    {
        "rules": {
            "favorites": {
                ".write": "newData.hasChild(auth.uid)",
                // This too: ".write": "newData.hasChildren([auth.uid])",
                "$owner_id": {
                    ".read": "root.child('favorites').child($owner_id) == auth.uid",
                    ".write": "root.child('favorites').child($owner_id) == auth.uid",
                }
            }
        }
    }
    

    除了允许成功编写以下内容外,它还可以工作:

    "favorites": {
        "bad_data": "oops",
        "$owner_id": {
            "favoriteid_1": {
                "title": "google.com",
                "link": "www.google.com"
            }
        }
    }
    

    感觉我们需要像“onlyChildren”这样的选项,这样就可以防止编写任意数据的用例。

    有什么想法吗?

    2 回复  |  直到 7 年前
        1
  •  0
  •   JMA    7 年前

    问题可能出在您尝试获取不存在的节点的子节点时:

    “root.child('favorites').child($owner\u id)==身份验证uid”

    将规则更改为:

    {
       "rules": {
           "favorites": {
               ".validate": "newData.hasChild(auth.uid)",
               "$owner_id": {
                    ".read": "$owner_id === auth.uid",
                    ".write": "$owner_id === auth.uid"
               }
           }
       }
    }
    
        2
  •  0
  •   flipcode    7 年前

    我改变了我的方法,它似乎完成了任务。这基本上是说,你可以在这里写,只要你经过身份验证,并且你没有写空。。。但是如果你这样做了,那么在$owner\u id树中。。。

    1. $owner\u id必须与您的身份验证匹配。uid,确保只向您的位置写入。
    2. 需要“title”和“link”子级,以确保您不会在/收藏夹中写入任意数据。
    3. 数据类型必须正确,以确保良好的内部管理。

    以下是验证规则:

    {
        "rules": {
            "favorites": {
                ".write": "auth.uid != null && newData.val() != null",
                "$owner_id": {
                    ".read": "$owner_id == auth.uid",
                    ".validate": "$owner_id == auth.uid && 
                                  newData.hasChildren(['title', 'link']) &&
                                  newData.child('title').isString() && 
                                  newData.child('link').isString()"
                }
            }
        }
    }
    

    使现代化 添加了空值检查。