"捕获所有其他"Firebase数据库规则

Dan*_*ván 4 firebase firebase-security firebase-realtime-database

也许我从SQL的角度来解决这个问题太多了,但是我很难理解如何正确地限制哪些孩子应该被允许填充节点.

假设我想保留具有任意名称的产品记录.每个产品必须包含一个price,但不允许任何其他产品.

我天真的方法是向.validate需要newData来包含priceprice节点的产品添加规则,显式授予对节点的写访问权限,然后删除对节点的所有访问$other(有点像switch语句中的default子句):

{
    "rules": {
        "$product": {
            ".read": true,
            ".write": true,
            ".validate": "newData.hasChildren(['price'])",
            "price": {
                ".write": true,
                ".validate": "newData.isNumber()"
            },
            "$other": {
                ".read.": false,
                ".write": false,
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这不起作用.{"price": 1234, "foo": "bar"}仍然会接受添加新产品.但是,如果我添加".validate": false规则$other,{"price": 1234}则不接受任何内容(例如,不允许). (不管怎样,我做错了.)

有没有办法实现类似于我在这里尝试的东西?如果没有,在Firebase中限制数据结构的正确方法是什么?我应该这样做吗?如果我不这样做,是什么阻止用户用垃圾填充我的数据库?

Fra*_*len 7

您将在这里遇到一些常见的Firebase安全漏洞.最常见的是权限级联:一旦您在树中的某个级别上授予了读取或写入权限,就不能在较低级别上取消该权限.

这意味着这些规则是无效的(因为您已经读/写权限提高了一级):

"$other": {
    ".read.": false,
    ".write": false,
}
Run Code Online (Sandbox Code Playgroud)

要解决此问题,您必须意识到.validate规则是不同的:只有在满足所有验证规则时,数据才被视为有效.因此,您可以$other使用验证规则拒绝数据:

{
    "rules": {
        "$product": {
            ".read": true,
            ".write": true,
            ".validate": "newData.hasChildren(['price'])",
            "price": {
                ".validate": "newData.isNumber()"
            },
            "$other": {
                ".validate": false
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)