android - Firestore 安全规则仅允许访问特定查询而不是整个集合
问题描述
鉴于以下简化的 Firebase Firestore 数据库结构:
users
user1
email: "test1@test.com"
user2
email: "test2@test.com"
我希望能够查询数据库中是否存在具有特定电子邮件的用户而不授予对整个users
集合的访问权限
是否可以在不修改数据库结构的情况下使用数据库规则来实现这一点?
如果不可能,那么最好的解决方法是什么?
我看到了两种可能的解决方案,但在我看来它们增加了太多的复杂性:
- 通过 API 端点公开该特定查询(可能使用 Firebase 函数)
- 按照此线程中的建议修改数据库结构:Firestore security rules based on request query value
您认为哪种方法更好?
解决方案
为了满足要求,“在不授予对整个用户集合的访问权限的情况下,查询数据库中是否存在具有特定电子邮件的用户”,您需要重新考虑您的数据库架构。Firestore 不允许您查询您也没有读取权限的数据。
我建议创建一个单独的集合,其中仅包含正在使用的电子邮件地址,如下所示:
{
"emails": {
"jane@example.com": { userId: "abc123" },
"sally@example.com": { userId: "xyz987" },
"joe@example.com": { userId: "lmn456" }
}
}
每次添加用户或更改电子邮件地址时,都应更新此集合。
然后像这样设置您的 Firestore 规则:
service cloud.firestore {
match /databases/{database}/documents {
match /emails/{email} {
// Allow world-readable access if the email is guessed
allow get: if true;
// Prevent anyone from getting a list of emails
allow list: if false;
}
}
}
有了所有这些,您就可以安全地允许匿名查询以检查电子邮件是否存在,而无需打开和服,可以这么说。
列出所有电子邮件
firebase.firestore().collection('emails').get()
.then((results) => console.error("Email listing succeeded!"))
.catch((error) => console.log("Permission denied, your emails are safe."));
Result: "Permission denied, your emails are safe."
检查 joe@example.com 是否存在
firebase.firestore().collection('emails').doc('joe@example.com').get()
.then((node) => console.log({id: node.id, ...node.data()}))
.catch((error) => console.error(error));
Result: {"id": "joe@example.com": userId: "lmn456"}
检查 sam@example.com 是否存在
firebase.firestore().collection('emails').doc('sam@example.com').get()
.then((node) => console.log("sam@example.com exists!"))
.catch((error) => console.log("sam@example.com not found!"));
Result: sam@example.com not found!
推荐阅读
- javascript - 通过 PHP 流式传输时,Safari 中的音频持续时间总是返回无穷大
- html - 并排不同尺寸的图像?
- javascript - 我的代码有什么问题?我没有收到错误消息;我没有得到任何回应
- django - 如何限制表单 Django 2.2 中的字段?
- python - How to pass multiple dictionaries and access certain values?
- python - 如何将列表中的所有数字与另一个列表中的另一个数字相乘。(相同顺序)
- mysql - 如何检查表中的多个列是否为空
- r - 如何使用 leaflet.extras addControlGPS 获取 GPS 坐标
- javascript - 如何使变量“计数器”计算随机创建并通过单击消失的“div”的数量
- swift - 试图制作一个类似的按钮,但在隐式展开可选值时意外发现 nil