Firebase基于数据键读取规则

时间:2017-08-29 23:18:39

标签: firebase firebase-realtime-database firebase-security

我的数据有以下结构:

writings: {
    'xxx-key-xxx': {
        'user-id': 'xxxxx',
        'title': 'title',
        'content': 'content'
    }
}

我试图只允许用户对他的文档进行读取访问:

{
  "rules": {
    "writings": {
        ".read": "auth !== null && (root.child('writings').child('user-id').val() === auth.uid)",
        }
    }
}

但这不起作用。我怀疑我没有正确地装上孩子user-id键。有什么想法吗?

1 个答案:

答案 0 :(得分:4)

您正在将auth.uid与缺少密钥/writings/user-id的路径xxx-key-xxx的值进行比较,因此这将始终为false,因为此路径中的数据不存在。您可以更改规则以获取孩子的密钥,但这会限制您.read阅读单个writings孩子的权限,例如

{
  "writings": {
    "$wid": {
      ".read": "auth !== null && root.child('writings/$wid/user-id').val() === auth.uid"

或等效

      ".read": "auth !== null && data.child('user-id').val() === auth.uid"
    }
  }
}

使用这些规则时,您会在尝试阅读Permission Denied时看到/writings - 您必须单独阅读这些文档,因此您必须知道每个文档的密钥。现在我们知道我们需要的是每个文档的键,我们需要找到一种检索它们的方法。

表示这种关系的常用方法是扇出数据。我们有uid用户,我们想要他们拥有的文件的密钥。如果您要维护另一个根节点,该节点存储每个用户只能访问的文档的密钥,那么您可以参考该位置来检索用户的文档。

{
  "user-writings": {
    "$uid": {
      ".read": "auth.uid === $uid",
      "$wid": {
        ".write": "auth.uid === $uid"
      }
    }
  },
  "users": {
    ...
  },
  "writings": {
    "$wid": {
      ".read": "auth.uid === data.child('user-id').val()",
      ".write": "auth.uid === newData.child('user-id').val()"
    }
  }
}

这些规则确保用户只能通过访问user-writings/$uid中的文档密钥来查看自己的文档。当用户创建书写时,他们还需要写入user-writings/$uid/$wid将值设置为true

现在要检索属于用户的文档,您可以使用用户的uid查询位置user-writings/$uid以检索密钥,然后必须获取每个writings/$wid的数据用户拥有。您可能适合完全抛弃writings并将每个用户的文档存储在数据库中的相应位置(user-writings/$uid)。