无法为 Android 应用程序的特定经过身份验证的用户 (uid) 编写***集合(列表权限)的 Firestore 安全规则

Posted

技术标签:

【中文标题】无法为 Android 应用程序的特定经过身份验证的用户 (uid) 编写***集合(列表权限)的 Firestore 安全规则【英文标题】:Can not write firestore security rule for top level collection (list permission) given a specific authenticated user (uid) for an android app 【发布时间】:2021-12-21 14:22:23 【问题描述】:

我刚开始使用 Firebase 服务(firestore),但我不明白为什么以下内容不起作用。

这是我的安全规则文件:

rules_version = '2';
service cloud.firestore 
  match /databases/database/documents/document=** 
    allow read, write: if request.auth.uid == resource.data.user_id;
  

我的数据库结构如下:

名为 备忘录 的***集合包含文档。在我的示例中,我只有一个“H5i5p0zenBwkV7vsS12G”。它以其自动生成的 id 命名。该文档有 2 个数据字段。一个“user_id”字符串数据等于“7llpal4k0xVxILawceAPPsJe3Vy1”,一个“title”字符串数据等于“Hello Firestore User”。

   /memos/H5i5p0zenBwkV7vsS12G with some data: 
      title: "Hello Firestore User"
      user_id: "7llpal4k0xVxILawceAPPsJe3Vy1"
    

当我使用测试工具和我的 android 应用程序运行 get (/databases/(default)/documents/memos/H5i5p0zenBwkV7vsS12G) 操作时,它可以完美运行。

但每次我使用

请求备忘录集合列表时
Firebase.firestore.collection("memos")

它失败并出现权限被拒绝异常。以下是相关日志:

2021-11-08 19:36:00.946 2996-3045/com.ygoular.memo I/Firestore: (23.0.4) [WatchStream]: (e04cf9f) Stream sending: # com.google.firestore.v1.ListenRequest@7a872c89
      add_target 
        query 
          parent: "projects/memo-da978/databases/(default)/documents"
          structured_query 
            from 
              collection_id: "memos"
            
            order_by 
              direction: ASCENDING
              direction_value: 1
              field 
                field_path: "__name__"
              
            
          
        
        target_id: 2
      
      database: "projects/memo-da978/databases/(default)"
2021-11-08 19:36:00.946 2996-3045/com.ygoular.memo I/Firestore: (23.0.4) [FirestoreCallCredentials]: Successfully fetched token.

2021-11-08 19:53:05.815 4440-4480/com.ygoular.memo I/Firestore: (23.0.4) [WatchStream]: (2faa0c0) Stream received: # com.google.firestore.v1.ListenResponse@c4bcaabe
    target_change 
      cause 
        code: 7
        message: "Missing or insufficient permissions."
      
      target_change_type: REMOVE
      target_change_type_value: 2
      target_ids: 2
    

此调用是在通过身份验证后进行的。我确信我的应用程序当时已通过身份验证,因为如果我使用以下内容修改安全规则:

allow read, write: if request.auth.uid != null

它传递并返回可用的备忘录。我也确定用户 ID 应该匹配,因为我粘贴了由返回的值

FirebaseAuth.getInstance().currentUser.uid

在执行电话身份验证后到数据库中的备忘录“user_id”字段。该提供商(电话)的此 ID 永远不会更改。

这里是从logcat获取的uid:

2021-11-08 19:53:05.633 4440-4440/com.ygoular.memo E/Test: uid: 7llpal4k0xVxILawceAPPsJe3Vy1

我可以完成这项工作的唯一方法是创建一个***集合 /users,它的文档名称作为它的用户 ID。在这种情况下,文档包含子集合 /memos,规则看起来像这样:

rules_version = '2';
service cloud.firestore 
  match /databases/database/documents/users/userId/anythingBehind=** 
    allow read, write: if request.auth.uid == userId;
  

如果您知道如何解决此问题,请告诉我! :) 非常感谢。

【问题讨论】:

【参考方案1】:

规则不是过滤器

我再重复一遍

规则不是过滤器

其实我还是让文档再重复一遍吧:

https://firebase.google.com/docs/firestore/security/rules-query

规则不会检查每条记录以查看是否每条记录都被允许。规则检查查询是否为写的 可能 匹配不允许的记录 - 在这种情况下,不允许 ENTIRE QUERY。它甚至不会检查其中一条记录是否有效 - 您必须执行至少指定 user_Id 字段的查询。

【讨论】:

是的,这就是我刚刚发现的。我回到这里结束话题,但你太快了! :D 非常感谢您的澄清。 Firebase.firestore.collection("memos").whereEqualTo("user_id", "7llpal4k0xVxILawceAPPsJe3Vy1") 这很好用!我的错误是认为 Firebase SDK 会自动向 Firestore 说当前 user_id 是“7llpal4k0xVxILawceAPPsJe3Vy1”以请求备忘录,但必须显式查询它,以便安全规则可以在不查看基础数据的情况下验证查询。非常感谢@LeadDreamer :)。

以上是关于无法为 Android 应用程序的特定经过身份验证的用户 (uid) 编写***集合(列表权限)的 Firestore 安全规则的主要内容,如果未能解决你的问题,请参考以下文章

从 android/ios 使用 Symfony 进行身份验证

如何从 android 客户端进行经过身份验证的 django rest api 调用?

错误:Google Drive嵌入视频无法为未经过身份验证的用户播放

谷歌云存储限制下载使用

Google+ 登录按钮 - 无法进行经过身份验证的呼叫

如何检查用户是不是经过身份验证以访问特定路径(MEAN STACK)