【问题标题】:How to add rule in Firebase to prevent read of parent element?如何在 Firebase 中添加规则以防止读取父元素?
【发布时间】:2022-01-15 18:15:13
【问题描述】:

我有一个 Firebase 数据库,我希望只允许有权访问该应用程序的用户读取和写入。

我的数据结构是这样的:

{
  "applications": {
    "id_1": {
      "feature": {
        "a": true,
        "b": false
      },
      "users": {
        "user_id_1": true,
        "user_id_2": true
      }
    }
  }
}

如您所见,每个应用程序都可以有许多具有读/写权限的用户。

我只希望users 对象中的用户能够检索该应用程序。

我有这样的规则:

{
  "rules": {
    "applications": {
      ".read": "auth != null",
      ".write": "auth != null",
      "$appId": {
        ".write": "data.child('users').child(auth.uid).val() === true",
        ".read": "data.child('users').child(auth.uid).val() === true"
      }
    }
  }
}

".read": "auth != null", 允许任何已登录的用户检索所有应用程序。我只希望用户 user_id_1user_id_2 能够读取该应用程序。

在伪代码中,我会这样做:

{
  "rules": {
    "applications": {
      ".read": "only users in `root.applications.$appId.users` can read", // I need to replace `$appId` some how
      ".write": "auth != null",
      "$appId": {
        ".write": "data.child('users').child(auth.uid).val() === true",
        ".read": "data.child('users').child(auth.uid).val() === true"
      }
    }
  }
}

我该如何限制它,以便当用户 user_id_1 获取他们的应用程序时,他们只能看到他们有权访问的应用程序?

【问题讨论】:

  • Firebase 实时数据库和 Cloud Firestore 是两个独立的数据库。请仅使用相关标签标记您的问题,不要同时使用两者。

标签: firebase firebase-realtime-database firebase-authentication firebase-security


【解决方案1】:

您在这里遇到了一些常见问题,所以让我们一一解决。

1。安全规则无法过滤数据

您试图在/applications 的规则中控制用户尝试读取该节点时将返回的应用程序。不幸的是,这是不可能的,因为安全规则授予全有或全无的访问权限。

因此,要么用户有权访问/applications(及其下的所有数据),要么他们无权访问它。您不能在 /applications 上设置规则来授予他们访问某些子节点的权限。

在文档中,这被称为rules are not filters,事实上permission cascades

2。避免嵌套数据

您尝试授予对/applications 的访问权限,但随后在其中为每个应用程序存储了两种类型的数据。在这种情况下,通常最好将每种类型的数据存储为自己的顶级列表。

所以在你的情况下,那就是:

{
  "application_features": {
    "id_1": {
      "a": true,
      "b": false
    },
  },
  "application_users": {
    "id_1": {
      "user_id_1": true,
      "user_id_2": true
    }
  }
}

这允许您为应用程序用户及其功能授予单独的访问权限。虽然这意味着您必须从两个分支读取以获取每个用户的所有信息,但性能差异可以忽略不计,因为 Firebase pipelines those requests over a single socket

为了控制访问和最具可扩展性的数据结构,Firebase 建议您使用avoid nesting dataflatten your data structure

3。对数据库中的数据进行建模以反映应用的屏幕

由于授予任何人对 /applications 的访问权限使他们能够访问其下的所有数据,因此您可能需要另一个地方来存储每个用户的应用程序列表。

我通常在我的数据库中明确列出这个列表,作为另一个顶级列表:

{
  ...
  "user_applications": {
    "user_id_1": {
      "id_1": true
    },
    "user_id_2": {
      "id_1": true
    }
  }
}

因此,现在当您想要显示当前用户的应用程序列表时,您可以从 /user_applications/$uid 加载 ID,然后通过额外调用查找每个应用程序的附加信息(这又可以再次通过管道传输)。

这个不在文档中,而是 NoSQL 数据库的常见模式。我建议查看我对Many to Many relationship in FirebaseFirebase query if child of child contains a value 的回答。

【讨论】:

  • 感谢弗兰克的详细回复。非常感谢。这些文档是有道理的,但我不明白的一件事是什么阻止任何用户更新user_applications 以让自己访问任何应用程序?即用户user_id_1 可以将属于user_id_2 的应用程序添加到user_application.user_id_id 对象。通过将users 嵌套在应用程序中,只有已经具有读取权限的用户才能添加用户,但如果我扁平化结构,这似乎是不可能的。也许它可以通过使用角色来处理?
  • 管理功能始终是特定于应用程序的,但对于任何一种数据模型都是可能的。例如,您可以检查作者的 UID 是否已存在于 /application_users/$appid/$uid 中。您甚至可以将他们的角色存储在那里("id_1": "admin""id_2": "user")并检查该特定值而不仅仅是存在。
猜你喜欢
  • 2018-02-21
  • 2021-08-13
  • 2012-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-23
  • 2016-02-25
  • 2019-03-05
相关资源
最近更新 更多