Firestore 的集合组权限

Jim*_*ane 3 firebase firebase-security google-cloud-firestore

我有这些规则:

match /suuntoAppAccessTokens/{userName} {
      allow create: if request.auth.uid != null && request.auth.token.firebase.sign_in_provider != 'anonymous';
      match /tokens/{userID} {
        allow read, write, create, update, delete: if request.auth.uid == userID && request.auth.token.firebase.sign_in_provider != 'anonymous';
      }
    }

match /{path=**}/tokens/{userID} {
            allow read, write, create, update, delete: if request.auth.uid == userID;
    }

Run Code Online (Sandbox Code Playgroud)

这意味着对于/suuntoAppAccessTokens/dimitrioskanellopoulos/tokens/{userID}当前用户应该具有访问权限的路径。

但是,当我像这样查询集合组时:

return this.afs.collectionGroup('tokens').snapshotChanges();
Run Code Online (Sandbox Code Playgroud)

我收到权限错误。

直接获取 tokes/{userID} 下的文档按预期工作。

我该怎么做才能让当前用户可以运行 collectionGroup 查询并根据我的规则获取他被允许获取的项目?

Dou*_*son 13

您的规则期望安全规则将过滤所有tokens集合中的所有文档,以便仅读取当前用户的文档。这对于安全规则是不可能的。 安全规则不是过滤器。文档

在编写查询以检索文档时,请记住安全规则不是过滤器——查询是全有或全无。为了节省您的时间和资源,Cloud Firestore 会根据查询的潜在结果集而不是所有文档的实际字段值来评估查询。如果查询可能返回客户端无权读取的文档,则整个请求都会失败。

您需要将您的查询更改为客户端仅请求完全期望当前用户可读的文档。不幸的是,我无法判断您当前的架构是否可行。不能在集合组查询中使用文档 {userId} 的 ID 来过滤文档。因此,您必须确保满足以下两个条件:

  • 您将需要文档中的一些字段,您可以对其进行过滤以完成这项工作。
  • 您将需要调整您的安全规则以准确匹配客户的要求。

我建议将用户的 uid 存储在带有令牌的文档中,与规则中的 {userId} 相同。你可以这样查询:

collectionGroup('tokens').where("uid", "==", uid)
Run Code Online (Sandbox Code Playgroud)

确保客户端正确传入 uid

此外,您需要确保规则按照完全相同的标准授予访问权限:

match /{path=**}/tokens/{userID} {
  allow read, write, create, update, delete:
    if request.auth.uid == resource.data.uid;
}
Run Code Online (Sandbox Code Playgroud)

如果它的 uid 字段与 auth uid 相同,这将只允许访问该文档,这正是客户端所要求的。

  • 我忽略的部分是以 `/{path=**/` 开始路径。 (4认同)