使用 Firebase 安全规则,如何在不使整个节点 public 的情况下检查可用的用户名?

Using Firebase Security rules, how can I check for available usernames without making the entire node public?

在我的 Firebase 数据库中,我有一个部分用于存储已使用的用户名。 有一个“usernames”节点,其中用户名是key,用户的ID存储在“userId”属性中。

usernames
{
    username1
        userId : "exampleId1"
    username2
        userId : "exampleId2"
    username3
        userId : "exampleId3"
    ...
}

当用户注册时,在他们创建帐户并通过身份验证之前,应用程序必须检查用户名是否未被占用。

为了使其正常工作,“用户名”节点已在 Firebase 安全规则中设置为 public:

"usernames": {
  ".read": true
}

不幸的是,这将使每个被占用的用户名和内部用户 ID 可见,这是一个安全问题,而不是应该做的事情。

(不知道的可以通过浏览器访问public个节点):

https://mydatabasename.firebaseio.com/usernames.json

还有其他以类似方式工作的用于禁止的用户名和电子邮件的节点;在用户通过身份验证之前必须检查它们,并且不应完全暴露给 public.

我的问题是:当用户注册时,如何在不创建整个节点的情况下检查可用的用户名public?

如果您喜欢这个主意,请告诉我。 :)

我将创建一个包含所有 func 和变量 private 的单例,它只会 return 一个 Bool 并采用 Username 变量。 这样就没有人可以从这部分访问数据或功能。无法注射。

在单例中你可以检查所有用户名并做任何你想做的事。 return 仅布尔值。

我想到了两个选项,第一个是允许 public 读取您的数据库,而第二个方法是我在实际项目中会做的:

方法一:维护一个单独的“用户名”节点

使用此方法您可以创建一个辅助节点,假设它被称为 usernamesInUse 并且这将是世界可读的。它的结构如下所示:

{
  "usernamesInUse": {
    "username1": true,
    "username2": true,
    "username3": true
  }
}

检查用户名是否存在非常简单:

db().ref('usernamesInUse/username2').once('value', (snapshot) => if (snapshot.exists()) ...)

此方法的缺点是,无论何时添加、修改或删除新用户,您都必须有适当的流程来更新此节点。但是,这将提供对用户名的安全读取访问权限。

方法二:创建云函数(我会怎么做)

创建一个带有 HTTPS 端点的简单 Cloud Function,用于检查用户名和 returns 200 或 404 状态代码是否存在。您的数据库不需要任何世界可读权限。

这避免了重复数据的需要,防止用户下载您系统中每个用户的完整列表,并防止世界对您的数据库进行不受限制的访问。您还有机会阻止滥用匿名访问者的访问权限。

要知道特定用户名是否已被占用,用户不需要 /usernames 的读取权限,但授予他们对 /usernames/$username 的读取权限就足够了。所以:

"usernames": {
  "$username": {
    ".read": true
  }
}

使用这些规则,您的代码可以检查用户想要声明的特定用户名是否已被(其他人)占用,但他们无法请求所有用户名的列表。