【问题标题】:Understanding the limits of Cloud Firestore's security rules了解 Cloud Firestore 安全规则的限制
【发布时间】:2018-05-17 02:28:28
【问题描述】:

我正在为我的 Firestore 数据库编写安全规则,但我可能编写了太多检查,授权自动失败。

例如特定路径的规则是

service cloud.firestore {
  match /databases/{database}/documents {
    match /pending/{userId} {
      match /rate/{vendorId}/events/{eventId}/ratings/{rateId} {
        allow write: if request.auth.uid == userId
            && exists(/databases/$(database)/documents/vendors/$(vendorId)) // The vendor must exist
            && exists(/databases/$(database)/documents/users/$(userId)/subscriptions/$(vendorId)) // The user must be subscribed to the vendor
            && exists(/databases/$(database)/documents/vendors/$(vendorId)/events/$(eventId)) //  The event must exist
            && !exists(/databases/$(database)/documents/vendors/$(vendorId)/events/$(eventId)/ratings/$(userId)) // The user must not have already voted for the event
      }
    }
  }
}

这些规则在写入 /pending/{userId}/rate/{vendorId}/events/{eventId}/ratings/{rateId}

时适用

删除一个或多个规则组合会使一切恢复正常。 我在文档中阅读了关于 10 个开发人员定义的函数 here 的限制,但存在和 get 被列为服务定义,不应计算在内。就算有,这里我也只用了五个。

有没有更有效的方法来检查相同的字段?如何计算达到 10 个函数限制的单行数?

谢谢

【问题讨论】:

  • “10 限制”在这里不是一个因素。它在调用深度调用深度限制为10个函数调用
  • 感谢您的回复。我实际上不确定如何确定我的数据库规则的调用深度。只是搜索“呼叫深度”并没有返回很多信息,你能链接我一些可能有用的资源吗?即使是几个例子也足够了。
  • 假设您编写了函数 A、B、C,其中 A 调用 B,B 调用 C。调用 A 的规则的调用深度为 3。调用深度不是问题的原因经历。您的帖子表明您可以注释掉任何一行并且该规则有效。对吗?
  • 哦,好的,谢谢,这真的很简单!是的,评论任何一行都可以解决问题(还没有尝试过第一行)
  • 我联系了支持人员,我会在获得更多数据后更新帖子。这确实很奇怪。再次感谢您的宝贵时间。

标签: firebase google-cloud-firestore firebase-security


【解决方案1】:

此处的 Firebase PM:目前,我们将给定规则评估中的 get()exists() 调用次数限制为三个,这就是为什么您在添加第四个后会看到行为失败的原因。我会确保适当更新文档以包含此信息。

编辑(2018 年 4 月 2 日):这些限制现已记录在案:https://firebase.google.com/docs/firestore/security/rules-structure#security_rule_limits

编辑(2018 年 5 月 14 日):我们将限制增加到 10:https://firebase.google.com/docs/firestore/security/rules-structure#security_rule_limits

get()exists() 调用比“正常”规则评估的计算成本更高,我们希望确保严格限制评估时间,以免减慢传入请求。我很确定我们可以将数字增加到 3 以上,但请注意,我们将查找所有这些键/值,并且评估每个请求可能需要更长的时间/更多的成本。

请注意,在这种特定情况下,您可以通过三个调用来做到这一点:

service cloud.firestore {
  match /databases/{database}/documents {
    match /pending/{userId} {
      match /rate/{vendorId}/events/{eventId}/ratings/{rateId} {
        // Only allow a document to be created
        allow create:
            // The user must not have already voted for the event
            if request.auth.uid == userId
            && request.auth.uid == rateId
            // The vendor must exist
            && exists(/databases/$(database)/documents/vendors/$(vendorId)) 
            // The user must be subscribed to the vendor
            && exists(/databases/$(database)/documents/users/$(userId)/subscriptions/$(vendorId)) 
            //  The event must exist
            && exists(/databases/$(database)/documents/vendors/$(vendorId)/events/$(eventId));
        // Not necessary unless you want to allow updates
        allow update: if ...;
      }
    }
  }
}

【讨论】:

  • 首先感谢您抽出宝贵时间解决此问题。我确信更新的文档将帮助很多将来可能遇到相同问题的人。我想再问你一件事,只是为了决定将来如何做:更复杂的应用程序可能会达到你对 exists() 调用设置的任何限制,所以我想我进行安全检查的方式本质上是有缺陷的.我应该检查函数本身中的所有这些字段吗?还是有更好的方法来确保只有“正确”的用户才能执行操作(客户端检查除外)?
  • 抱歉耽搁了,终于在这里深入了解了。您可以通过 3 次调用来解决此问题(不需要最后一次调用,因为您已经获得了数据)。
猜你喜欢
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 2018-04-05
  • 1970-01-01
  • 2018-07-23
相关资源
最近更新 更多