也许我从SQL的角度来解决这个问题太多了,但是我很难理解如何正确地限制哪些孩子应该被允许填充节点。
假设我想保留具有任意名称的产品记录。每个产品必须包含price
,但不允许任何其他内容。
我天真的方法是向需要newData的产品添加.validate
规则以包含price
子项,明确授予对price
节点的写访问权限,然后删除所有访问{ {1}}节点(有点像switch语句中的default子句):
$other
这不起作用。添加{
"rules": {
"$product": {
".read": true,
".write": true,
".validate": "newData.hasChildren(['price'])",
"price": {
".write": true,
".validate": "newData.isNumber()"
},
"$other": {
".read.": false,
".write": false,
}
}
}
}
的新产品仍然可以接受。 但是如果我向 (我做错了,不知。) {"price": 1234, "foo": "bar"}
添加".validate": false
规则,则不接受任何内容(例如,不允许$other
)。
有没有办法实现类似于我在这里尝试的东西?如果没有,在Firebase中限制数据结构的正确方法是什么?我应该这样做吗?如果我不这样做,是什么阻止用户用垃圾填充我的数据库?
答案 0 :(得分:7)
这里有一些常见的Firebase安全漏洞。最常见的一种是权限级联:一旦您在树中的某个级别上授予了读取或写入权限,就不能在较低级别上取消该权限。
这意味着这些规则无效(因为您已经授予读/写一级更高级别):
"$other": {
".read.": false,
".write": false,
}
要解决此问题,您必须意识到.validate
规则不同:只有在满足所有验证规则时,才认为数据有效。因此,您可以使用验证规则拒绝$other
数据:
{
"rules": {
"$product": {
".read": true,
".write": true,
".validate": "newData.hasChildren(['price'])",
"price": {
".validate": "newData.isNumber()"
},
"$other": {
".validate": false
}
}
}
}