【问题标题】:Securely querying data with firestore - Permission denied使用 Firestore 安全地查询数据 - 权限被拒绝
【发布时间】:2020-05-17 06:29:27
【问题描述】:

当我引入规则时,我在查询 Firestore 时遇到权限被拒绝错误。我已经缩小了我的复杂规则并过滤到以下 2 个示例,其中一个查询有效,一个查询无效。我不明白我失败的查询出了什么问题。

来自https://cloud.google.com/firestore/docs/security/rules-query 我了解规则不是过滤器。根据该文档:“如果查询可能返回客户端无权读取的文档,则整个请求将失败。”。

考虑到这一点,我一直在迭代我的规则、过滤器和数据,并提供以下内容:

数据: 我的集合中没有名为“MyCollection”的数据。事实上,集合“MyCollection”从未存在过。

规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    match /MyCollection/{id} {
      allow read: if (  
                       (resource.data.readAccess == 0)
                     )

      allow write: if (true)

    }
  }
}

我的失败查询(我的权限被拒绝错误):

Firestore.instance.collection('MyCollection')
      .where("readAccess", isLessThanOrEqualTo: 0)
      .getDocuments()
      .then((_) => print("Success!"));

当我运行此查询时,我收到以下错误:

W/Firestore(12491): (21.3.0) [Firestore]: Listen for Query(MyCollection where readAccess <= 0) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}

我的成功查询: (这个查询的唯一区别是我用 isEqualTo 替换了“isLessThanOrEqualTo”)

Firestore.instance.collection('MyCollection')
      .where("readAccess", isEqualTo: 0)
      .getDocuments()
      .then((_) => print("Success!"));

评论:

  • 当我用数据填充 MyCollection 时,我得到了相同的结果。
  • 看起来查询是根据规则验证的,而不是文档https://cloud.google.com/firestore/docs/security/rules-query 所述的“潜在返回文档”。如果是这种情况,我想知道如何将以下规则转换为过滤器:

                   (resource.data.readAccess == 0) || 
                   ((request.auth != null) && 
                    (resource.data.readAccess <= get(/databases/$(database)/documents/App/$(resource.data.appId)).data.group[request.auth.uid])
                   )
    
  • 此规则非常相似,只是它针对已登录用户的数据应用程序的“应用”文档中的组访问级别验证文档的 readAccess 级别。如果我无法匹配一个简单规则的查询,我无法想象我需要为这个复杂的规则做什么。

请指教。非常感谢。

【问题讨论】:

    标签: google-cloud-firestore firebase-security


    【解决方案1】:

    使用安全规则,查询必须与规则完全匹配。您观察到的行为正是我所期望的。

    使用这样的规则:

    allow read: if resource.data.readAccess == 0;
    

    这意味着必须完全像这样过滤查询;

    where("readAccess", isEqualTo: 0)
    

    没有其他东西可以满足这条规则。 要求查询过滤器在 readAccess 字段上的值正好为 0。我不清楚你为什么期待不同的结果。

    您的查询表明客户端提供了自己对集合的“访问权限”。请注意,这并不安全。您不能依赖客户端应用程序在数据库查询中自行报告自己的访问级别。后端的其他东西需要确定是否允许应用进行查询。

    通常,Firebase 身份验证用于确定用户是谁,然后根据允许该用户执行的操作来允许访问。您可以将用户的权限存储在另一个文档的某处,并使用该文档的内容来确定他们可以做什么。或者也许使用自定义声明。但是你不能相信用户传递了他们自己的权限。

    【讨论】:

    • 查询必须完全匹配权限是什么意思?这意味着无论何时您检查用户是否已登录,或者您正在检查资源对象中的数据变量,那么查询也必须包含这些内容。不检查用户是否有权在相关表中读/写几乎总是涉及执行查询中没有的操作?
    • 是的,它涉及查看请求、身份验证和可能的其他文件。
    • 那么查询与权限不匹配,因为查询不是仅在用户在其他文档中具有权限的情况下才调用文档?还是这样?
    • 对不起,我不明白这个问题。如果您的规则未指明有关用户的任何内容,则不存在基于用户的安全性。也许您想从文档开始:firebase.google.com/docs/firestore/solutions/role-based-access
    • 我的意思是,如果将“权限”存储在单独的表中,则客户端发送的查询不具有用户在该表中具有权限的条件。这是在后端处理的东西。
    猜你喜欢
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 2020-11-17
    • 2019-03-20
    • 1970-01-01
    • 2021-02-13
    • 2020-09-12
    • 2019-02-24
    相关资源
    最近更新 更多