【问题标题】:Public access to Firestore collection doc on condition有条件地公开访问 Firestore 集合文档
【发布时间】:2020-06-21 21:10:58
【问题描述】:
我需要允许公共访问集合,但仅用于查询特定文档且仅当它与前提条件匹配时。
例如,我有一个集合userdata,其中包含文档:
5a70afcd3b26d6a5: {
id: 7799389,
email: me@domain.com
...
}
我需要创建一个规则以仅在使用id 和email 查询集合(甚至在身份验证之前)时才允许read 访问,否则不允许。这可能吗?
【问题讨论】:
标签:
javascript
firebase
google-cloud-firestore
firebase-security
【解决方案1】:
我对您的要求的理解:您希望用户只有在事先知道某些特定字段的情况下才能从给定集合中检索文档。
对于您的示例,使用字段 id 和 email 的解决方案是将文档命名为 {id}_{email} 并仅提供获取规则。文档的名称本身就成为了秘密。
7799389_me@domain.com: {
id: 7799389, // May be omitted as already in the doc name
email: me@domain.com // May be omitted as already in the doc name
...
}
get: allow if... // additional conditions if needed
如果您不想或无法更改文档 ID,则需要根据用户请求将文档与某些条件匹配,如果用户未经身份验证,这几乎是不可能的。
【解决方案2】:
这在您当前的结构中是不可能的。但是,您可以通过在安全规则中利用 request.query 来解决问题。
例如
service cloud.firestore {
match /databases/{database}/documents {
match /userdata/{userid} {
// Deny any query not limited 1 and contains offset or orderBy.
allow list: if request.query.limit == 1 && !request.query.offset && !request.query.orderBy;
}
}
}
通过这样做,您只会将集合中的第一个文档公开,其他文档只能在特定条件下进行查询。
另一种可能的解决方案是像@Oliver 回答的那样重新组织您的收藏,并仅允许通过 ID 进行查询。但请注意在 ID 中使用特殊字符,例如 . 或 [。
最后但并非最不重要的一点是,编写一个接受 email 和 id 作为参数并返回 doc 作为结果的云函数。它可能比直接使用 firestore 慢。
【解决方案3】:
如果您的实际需要是只允许用户查看她自己的记录,我只是在徘徊?
如果是这样,我建议 -
-
要求用户首先通过 firebase 身份验证才能获得 firebase 身份验证令牌。
-
用户必须使用上述步骤中获得的firebase令牌登录到您的服务器。
-
在您的身份验证逻辑中,将嵌入在令牌中的 firebase UID 映射到用户 ID 和电子邮件。我假设您有一个表格(或确切地说,在 firebase 中的集合)来保存此类关系。
-
将上述步骤中获得的用户 ID 和电子邮件保存为 Firebase 令牌声明。这是 C# 代码示例,您应该可以在 javascript 中进行类似操作 -
等待 FirebaseAdmin.Auth.FirebaseAuth.DefaultInstance.SetCustomUserClaimsAsync(
用户界面,
新字典 {
{"user_id", userId},
{"user_email", userEmail }
});
-
创建以下数据规则以保证用户只能读取自己的记录-
match /userdata/{user} {
allow read: if resource.data.userid == request.auth.token.userid &&
resource.data.userEmail == request.auth.token.userEmail
}
如果 userid 足以唯一标识一个用户,则无需将 userEmail 保存在令牌声明中,也无需在规则中检查。