【问题标题】:Can't understand Firebase database rules无法理解 Firebase 数据库规则
【发布时间】:2016-06-11 16:02:36
【问题描述】:

这一定很容易做到,而且我正在做一些愚蠢的事情,但是 4 个小时我无法理解我做错了什么。 我有这样的数据库实体:

posts:
    -KK-3ajDuSUglnMMdXgy
       authorId: "DYI4TPbwQocFsVROStUqcGNFHhW2"
       authorName: "john"
       privacy: "PrivacyTypeWorld"
       text: "some post text"

帖子可以有 3 个级别的隐私:所有人 (PrivacyTypeWorld)、仅作者 (PrivacyTypePrivate) 和朋友 (friendId、friendId, ...)。

我的安全规则如下所示:

{
  "rules": {
     "posts": {
        ".read": "auth != null && (data.child('privacy').val() === 'PrivacyTypeWorld')",
        ".write": "auth != null"
      }
   }
}

但是有了这个规则,我什么都看不到。如果我设置".read": "auth != null" - 一切正常。 我做错了什么?

编辑:

要检索我使用的数据:

_refHandle = [[_ref child:@"posts"] observeEventType:FIRDataEventTypeChildAdded
                                      withBlock:^(FIRDataSnapshot *snapshot) {
                [_arrPosts addObject:snapshot];
                [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:_arrPosts.count-1 inSection:0]] withRowAnimation: UITableViewRowAnimationAutomatic];
          }];

【问题讨论】:

  • 您的规则缺少一个级别。要访问每个节点,您需要一个变量...例如在本例中为 $post_id,然后您可以引用(一般来说)$post_id/privacy = 'whatever'。请参阅 Structuring Your Rules 部分中大约 1/2 处的 Secure Your Data。否则,您正在寻找帖子/隐私,其中应该是帖子/post_id/privacy。
  • 您能否将无效的代码添加到您的问题中?
  • @FrankvanPuffelen,什么代码?我可以在 Firebase 控制台中看到实际添加的数据 (dropbox.com/s/shbfrob1af8o405/…) 和规则 loojs,如 adolfosrs 回答
  • @daleijn 他的意思是你的快速代码。您如何尝试检索数据...
  • @adolfosrs,更新问题

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


【解决方案1】:

你有两个错误:

  1. 您的规则定义了错误级别的访问(正如@adolfosrs 所说)。通过意识到没有节点posts/privacy 是最容易理解的,因此检查将始终返回false。相反,您应该授予对posts/$postid 的访问权限,以便检查posts/$postid/privacy

  2. 您正在尝试阅读posts。 Firebase 查询始终检查您读取/查询的级别的权限。由于您未授予对 posts 的读取权限,因此查询将失败。

最后一位通常称为"rules are not filters" or "rules cannot be used to filter data"。最好的答案是Restricting child/field access with security rules

在您的情况下,最简单的解决方案似乎是将全球可读的帖子放在一个单独的顶级节点下,您可以在该节点授予每个人读取权限:

posts:
    -KK-3ajDuSUglnMMdXgy
       authorId: "DYIciaiew98acohzxvx09qw"
       authorName: "puf"
       text: "Only authenticated users can write this"
publicPosts:
    -KK-3ajDuSUglnMMdXgy
       authorId: "DYI4TPbwQocFsVROStUqcGNFHhW2"
       authorName: "john"
       text: "Everyone can read this"

这些规则:

{
  "rules": {
     "posts": {
        ".read": "auth != null",
        ".write": "auth != null"
      }
     "publicPosts": {
        ".read": true,
        ".write": "auth != null"
      }
   }
}

【讨论】:

  • 如果隐私设置仅适用于某些朋友(friendId、friendId、...)。我该如何实施?为什么@adolfosrs 的回答不起作用?我必须更改我的数据库结构中的某些内容还是什么?
  • 但是如果我将此规则(如在@adolfosrs 回答中)设置为 .write(仅更改数据 -> newData) - 这可以按预期工作,我只能在“隐私”=== 时添加帖子'隐私类型世界'。为什么这不适用于 .read?
  • 当你写作时,你正在写一个特定的帖子 (/posts/-KK-3ajDuSUglnMMdXgy)。但是当您查询时,您正在从没有读取权限的列表 (/posts) 中读取。
  • 如果每个用户都可以访问不同的帖子,您必须保留每个用户可以访问的帖子(或帖子 ID)列表。这在 NoSQL 数据建模中是很正常的。我强烈建议花一些时间阅读this article on the topic
  • 限定词“数据”不适用于这种情况(检查数据库中已有的数据)?
【解决方案2】:

您不会进入每个帖子。您正在查看帖子中的隐私,而不是帖子/postId。

在以下规则中,$post 指的是帖子 ID。因此,如果您想进行任何其他验证,您也可以在读取或写入时使用 $post 来处理帖子 ID。

{
  "rules": {
     "posts": {
        "$post": {
            ".read": "auth != null && (data.child('privacy').val() === 'PrivacyTypeWorld')",
            ".write": "auth != null"
        }
      }
   }
}

【讨论】:

    猜你喜欢
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多