应将哪些安全规则应用于Firebase中的读取?应用于、应将、规则、安全

2023-09-04 22:45:58 作者:娇气包

我为一家戏剧公司创建了一个网站,上面有他们即将上演的剧目的清单。 这些日期存储在FireStore中,所以我设置了一些规则:

数据-lang="js"数据-隐藏="假"数据-控制台="真"数据-巴贝尔="假">
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
  
    match /{document=**} {
      allow read: if true;
    }
    match /{document=**} {
        allow write: if request.auth != null;
    }
  }
}

我只希望管理员在登录时能够写入,但我希望每个人都能够访问数据库以读取日期。

Google Cloud Firebase 讲解

我以为还可以,但我每天都会收到一封来自Firebase的新电子邮件,说数据库不安全,因为任何人都可以读取我的数据。

我应该做什么?

推荐答案

您的安全规则应该只允许代码需要的内容,而不允许其他内容。这被称为最小特权原则,是确保恶意用户不能比您自己的代码执行更多操作的最佳方式。

让我们依次了解如何使读取和写入更安全。

保护读取

您的规则当前允许任何人读取整个数据库。但是您的代码并不读取整个数据库。取而代之的是,它只读取即将播出的节目的列表。因此,您应该只允许阅读即将播出的节目:

match /databases/{database}/documents {

  match /upcoming_shows/{document} {
    allow read: if true;
  }

所以现在用户只能从单个集合中读取:名为upcoming_shows的集合。

如果您实际上有一个所有节目的列表,并且您的代码只读取using a query即将到来的节目,则您还可以secure that query以使阅读所有节目的人被拒绝。

正如开头所说:您的规则应该只允许代码要求的内容,而不允许其他内容。

保护写入

您说应该只允许管理员在登录时写入数据。但现在,任何登录到Firebase身份验证的人都可以在您的整个数据库中编写任何他们想要的内容。因此,恶意用户可以从您的应用程序中获取配置,使用该配置调用Firebase进行登录,然后例如删除您的所有数据,向其中添加他们自己的假节目,或者只是在数据库中创建一个完全不同的数据集,然后您就可以为其付费。

您需要更好地保护两个部分:

只有管理员才能写入。 他们只能添加节目。

只有管理员才能写入

您似乎认识管理员,所以您可能可以在Firebase控制台中找到他们的UID,并简单地在您的规则中对其进行硬编码:

allow write: if request.auth == "uid of your known administrator";

现在有了这些规则,因为Firebase确定了用户的UID,并且它不能被欺骗,所以您已经确保只有您标识的一个人可以写入数据库。

此模式有许多变体,但这是很好的第一步。

他们只能添加节目

通过以上更改,我们已经确保只有管理员可以写入,但他们仍然可以随心所欲地写入。最小特权原则规定,我们应该确保他们也只能写入他们必须能够写入的内容。在您的案例中,这就是添加新节目。

这又分解为两个要求:

管理员只能写入节目,这意味着他们无法写入其他类型的数据,也不能将数据写入数据库中的其他位置。

管理员只能添加节目,这意味着他们无法更新或删除它们。

仅允许写入节目

第一个要求同样是双重的,第一个类似于我们对读取所做的:我们希望确保它们只能写入upcoming_shows集合:

match /upcoming_shows/{document} {
    allow write: if request.auth == "uid of your known administrator";
}

第二部分是它们只能在那里写show,这意味着您将想要validate the data that they write。您将希望只允许代码实际编写的字段,因为(再一次)规则应该只允许代码所做的事情,除此之外什么也不允许。这可能包括验证节目的日期是否在将来,如果这也是您的用例所需要的。

仅允许添加节目,不允许更新/删除它们

最后,您的用例说明它们只能添加节目,我认为这不能更新和/或删除它们。我们可以使用granular rules来实现该要求:

match /upcoming_shows/{document} {
    allow create: if request.auth == "uid of your known administrator" &&
                  /* the validation rules from the previous step */;
}