我有一个用户集合,其中存储用户数据,例如姓名、电子邮件等,以及另一个用于被阻止用户的集合。我想允许用户阅读自己的文档以及他/她没有阻止的用户的文档。我已经实现了安全规则,但不知何故,用户甚至无法阅读自己的文档。有人可以帮忙吗?
用户集合
users { // name of collection
a1 { // this is firebase id serving as document name
name: "abc",
email: <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1d7c7f7e5d7a707c7471337e7270" rel="noreferrer noopener nofollow">[email protected]</a>
}
a2 { // this is firebase id serving as document name
name: "efg",
email: <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d5b0b3b295b2b8b4bcb9fbb6bab8" rel="noreferrer noopener nofollow">[email protected]</a>
}
a3 { // this is firebase id serving as document name
name: "hij",
email: <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a5cdcccfe5c2c8c4ccc98bc6cac8" rel="noreferrer noopener nofollow">[email protected]</a>
}
a4 { // this is firebase id serving as document name
name: "klm",
email: <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="107b7c7d50777d71797c3e737f7d" rel="noreferrer noopener nofollow">[email protected]</a>
}
}
阻止收藏
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();
最佳答案
在这种情况下,您需要以不同的方式处理 userId
变量。按照您编写的方式,规则是在用户被阻止文档的 Resource
对象中查找 userId
属性,而不是 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
- user
a2
读取/users
中的任何文档
以上应该否认:
- 全部写入
- 用户
a1
读取/users/a2
我只在模拟器中对上述内容进行了一些松散的验证。强烈推荐您write extensive tests对于您最终使用的任何规则。
最后,请记住 security rules are not filters ,所以这实际上取决于您如何使用它 - 可能拒绝任何可能匹配的文档的查询将拒绝整个查询。您描述问题的方式(使用拒绝用户访问他们已阻止的其他用户的文档的规则)听起来像是您正在尝试过滤,而不是试图保护数据。
关于firebase - Firestore 安全规则 - 权限被拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59055605/