2016-08-22 47 views
4

也许我从SQL类型的角度来解决这个问题太多了,但我在理解如何正确限制哪些孩子应该被允许填充节点时遇到了麻烦。“捕获所有其他”Firebase数据库规则

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

我幼稚的方法是添加一个.validate规则要求newData产品包含一个price孩子,明确授予的price节点的写入权限,然后删除所有访问$other节点(有点像在一个switch语句中违约条款):

{ 
    "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,则不会接受任何内容(例如,不允许使用{"price": 1234})。(我做错了,不知何故。)

是否有某种方法来实现类似于我在这里要做的事情?如果没有,限制Firebase中数据结构的正确方法是什么?我应该这样做吗?如果我不知道什么会阻止用户使用垃圾填充数据库?

+0

我不知道我为什么跟着'“$其他”:{“.validate”:假}'是不是你想要的。但是,无视这一点,您是否意识到一旦授予您不能撤销权限?所以'$ product'下的''.write“:true'意味着''其他'下的''.write”:false'会被忽略? – cartant

+0

@cartant我更新了这个问题,以澄清为什么验证不起作用。 –

回答

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 
      } 
     } 
    } 
} 
+0

这解决了它。有趣的是,我认为我已经尝试了这个解决方案(就像我在问题中简单提到的那样),但显然我设法弄明白了。无论哪种方式,您的答案也使得验证和写作之间的差异更加清晰,所以我非常感谢您。 :) –

+0

这是怎么看螺栓? – Waltari