【问题标题】:Firestore security rules to allow access only to specific queries and not the whole collectionFirestore 安全规则仅允许访问特定查询而不是整个集合
【发布时间】:2021-05-13 07:59:08
【问题描述】:

鉴于以下简化的 Firebase Firestore 数据库结构:

  users
    user1
      email: "test1@test.com"
    user2
      email: "test2@test.com"

我希望能够查询具有特定电子邮件的用户是否存在于数据库中,而无需访问整个 users 集合

是否可以在不修改数据库结构的情况下使用数据库规则来实现?

如果不可能,最好的解决方法是什么?

我看到了两种可能的解决方案,但在我看来它们增加了太多复杂性:

  1. 通过 API 端点公开特定查询(可能使用 Firebase 函数)
  2. 按照此线程中的建议修改数据库结构:Firestore security rules based on request query value

您认为哪种方法更好?

【问题讨论】:

  • 我认为这是不可能的,但我正在使用另一种解决方案。只需使用不同的密钥加密您的数据即可使用用户密码密钥进行所有条目。就像其他人使用您的 api id 来请求您的数据一样,他们将无法破译它们。
  • 我也觉得无法满足确切的要求。您可以参考下面的链接以深入了解规则。 firebase.google.com/docs/firestore/security/get-started

标签: android firebase google-cloud-firestore


【解决方案1】:

为了满足要求,“在不授予对整个用户集合的访问权限的情况下,查询数据库中是否存在具有特定电子邮件的用户,”您需要重新考虑您的数据库架构。 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!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 2021-02-13
    相关资源
    最近更新 更多