Firestore安全规则-权限被拒绝

时间:2019-11-26 16:40:37

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

我有一个用户集合,我在其中存储用户数据,例如姓名,电子邮件等,以及另一个用于阻止用户的集合。我想允许用户阅读自己的文档以及他/她没有阻止的用户文档。我已经实现了安全规则,但是用户不知何故甚至无法阅读自己的文档。有人可以帮忙吗?

用户集合

users { // name of collection
   a1 { // this is firebase id serving as document name
     name: "abc",
     email: abc@gmail.com
   }
   a2 { // this is firebase id serving as document name
     name: "efg",
     email: efg@gmail.com
   }
   a3 { // this is firebase id serving as document name
     name: "hij",
     email: hij@gmail.com
   }
   a4 { // this is firebase id serving as document name
     name: "klm",
     email: klm@gmail.com
   }
}

阻止的收藏集

blocked { // name of the collection
    a1 { // name of the document
        a2 : 1, // this means a1 has blocked a2
        a4 : 1  // this means a1 has blocked a4
    }
}

安全规则

service cloud.firestore {
    match /databases/{database}/documents {
        match /users/{userId} {
            allow read: if request.auth.uid != null
            && get(/databases/$(database)/documents/blocked/$(request.auth.uid)).userId != 1;
        }

        match /blocked/{fid} { // blocked collection/fid == owner firebase id
            allow read: if request.auth.uid == fid;
        }
    }
}

代码

DocumentReference docref = Firestore.instance.collection("users").document(user.uid);
return docref.get();

1 个答案:

答案 0 :(得分:2)

在这种情况下,您需要对userId变量进行不同的处理。编写方式的规则是,在用户阻止的文档的userId对象中寻找Resource属性,而不是userId变量的值。您可能还想为get调用提供一个合理的默认值。

同样,由于get()调用返回一个Resource,因此您需要使用data成员来获取属性Map

您可能需要另外检查用户的被阻止文档是否确实存在,否则查询将失败。

service cloud.firestore {
    match /databases/{database}/documents {
        match /users/{userId} {
            allow read: if request.auth.uid != null
                && (!exists(/databases/$(database)/documents/blocked/$(request.auth.uid)) ||
                    get(/databases/$(database)/documents/blocked/$(request.auth.uid)).data.get(userId,0) != 1);
        }

        match /blocked/{fid} { // blocked collection/fid == owner firebase id
            allow read: if request.auth.uid == fid;
        }
    }
}

以上内容应允许(考虑到您在问题中定义的/blocked):

  • 用户a1阅读/users/a1
  • 用户a1阅读/users/a3
  • 用户a2读取/users中的任何文档

以上内容应否认:

  • 所有写
  • 用户a1阅读/users/a2

我只在模拟器中对以上内容进行了一些宽松的验证。我强烈建议您write extensive tests使用最终使用的任何规则。

最后,请记住security rules are not filters,所以它实际上取决于您的使用方式-可能会拒绝任何个可能匹配文档的查询将拒绝整个查询。您描述问题的方式(使用拒绝用户访问其阻止的其他用户的文档的规则)听起来就像您在尝试过滤而不是在保护数据。