【问题标题】:Limit users read/write access to firebase nodes is not working限制用户对 firebase 节点的读/写访问权限不起作用
【发布时间】:2019-01-23 17:50:08
【问题描述】:

我有一个带有几个根节点的 firebase 数据库结构(对于这个问题,只有几个很重要):buildingsbuildingsUserIdbuildingsUserUid 的意图 是控制用户访问他们的建筑物和只访问他们的建筑物)。

如果我们更深入地研究两个节点的结构,我们会得到以下信息:

users
  `-- userID // one user can access this 
  |   `-- isAdmin
  |       `-- building pushkey
  |       `-- another building pushkey etc.
  `-- another userID // one user can access this 
  |   `-- isAdmin
  |       `-- building pushkey
  |       `-- another building pushkey etc.
  `-- another user UID etc.


buildingsUserUid
  `-- firebase user UID // one user can access this 
  |   `-- building pushkey
  |   `-- another building pushkey
  `-- another firebase user UID // another user can access this 
      `-- yet another building pushkey 
      `-- and another building pushkey etc.

buildings
 `-- building pushkeys // user with right UID can access this
 |   |-- firebase user UID
 |   `-- Other data
 `-- building pushkeys  //another user with right UID can access this
     |-- firebase user UID
     `-- Other data

那么我的firebase规则是这样的:

{
  "rules": {
      "users": {
          "$uid": {
            ".read": "auth.uid == $uid",
            ".write": "auth != null && $uid === auth.uid",
          }
      },
      "buildings": {
         ".read": "root.child('buildingsUserUid').hasChild(auth.uid)",
         ".write": "!data.exists() || root.child('buildingsUserUid').hasChild(auth.uid)",
            "$pushkey": {
                ".read": "root.child('buildingsUserUid').child(auth.uid).hasChild($pushkey)",
                ".write": "!data.exists() || root.child('buildingsUserUid').child(auth.uid).hasChild($pushkey)",
             }
      },
      "buildingsUserUid": {
         "$user": {
             ".read": "auth != null && auth.uid === $user",
             ".write": "auth != null && auth.uid === $user"
          }
      },
 }

通过上述规则,我希望将访问建筑物节点的权限仅限于在其 buildingUserUid 节点上拥有建筑物按钮的用户。但是,如果我 console.log(this) 在我的 vue.js 应用程序上,我可以看到所有建筑物。

这是因为我正在从应用程序记录 this,还是用户能够以相同的方式从浏览器控制台访问 this?我的规则是否遗漏了什么?

更新:

根据@Umar 的回答,我已将规则更改为:

{
  "rules": {
      "users": {
          "$uid": {
            ".read": "auth.uid == $uid",
            ".write": "auth != null && $uid === auth.uid",
          }
      },
      "buildings": {
         ".read": "root.child('buildingsUserUid').hasChild(auth.uid)",
         ".write": "!data.exists() || root.child('buildingsUserUid').hasChild(auth.uid)",
            "$pushkey": {
                // changed the following 'read' rule line
                ".read": "root.child('buildingsUserUid').child($pushkey).child('userId') === auth.uid"
                ".write": "!data.exists() || root.child('buildingsUserUid').child(auth.uid).hasChild($pushkey)",
             }
      },
      "buildingsUserUid": {
         "$user": {
             ".read": "auth != null && auth.uid === $user",
             ".write": "auth != null && auth.uid === $user"
          }
      },
 }

但这会触发错误:

错误保存规则 - 第 15 行:无效 == 表达式:左操作数不是数字、布尔值、字符串、空值。 ——

有什么想法吗?

【问题讨论】:

    标签: javascript firebase-realtime-database vuejs2 firebase-security


    【解决方案1】:

    通过将".read": "root.child('buildingsUserUid').hasChild(auth.uid)" 设置为buildings,您实际上允许任何建筑物的任何用户读取所有建筑物节点数据。

    您必须允许读取访问低于上一级,即在pushkey 下。此外,如果您只将一位用户与一栋建筑物相关联,您可以简单地将建筑物 ID 存储在用户节点下,而不是在建筑物的按键下。

    为你当前的结构pushkey读可以

    ".read": "root.child('buildingsUserUid').child($pushkey).child('userId') === auth.uid"

    我假设每个建筑物都有一个用户,并且用户的 uid 与密钥 userId 一起存储在“pushkey”下

    【讨论】:

    • 谢谢@Umar。我将一个用户关联到多个建筑物(这些建筑物最终可能由多个用户共享)。这个规则还会有效吗?只是为了完全确定新行将放置在 buildings 规则或 buildings/$pushkey 下?
    • 我假设在 buildings/$pushkey 下是这样的:"buildings": { ".read": "root.child('buildingsUserUid').hasChild(auth.uid)", ".write": "!data.exists() || root.child('buildingsUserUid').hasChild(auth.uid)", "$pushkey": { ".read": "root.child('buildingsUserUid').child($pushkey).child('userId') == auth.uid", ".write": "!data.exists() || root.child('buildingsUserUid').child(auth.uid).hasChild($pushkey)", } }, 但这会导致错误 Error saving rules – Line 15: Invalid == expression: left operand is not a number, boolean, string, null.
    • 如果您想将一个用户关联到多个建筑物,那么这种结构将无法有效工作。例如,您将需要获取用户的所有建筑物,但您不想让其他用户知道这种关系。您可以做的是在每个用户下嵌套一个建筑物节点,并在您想向用户添加建筑物时添加 buildingId。然后您可以打开根 Buildings 节点进行安全读取。
    • 嗨@Umar!我实际上已经用这样的节点抢先构建了应用程序:users/isAdmin/buildingID。我认为 buildingsUserUidbuildings 节点足以解决此问题,因此我将其发布在这里。我正在将用户节点结构添加到问题中,也许您可​​以帮助我制定规则。非常感谢您迄今为止的意见。
    猜你喜欢
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 2019-02-26
    • 2017-04-11
    • 1970-01-01
    相关资源
    最近更新 更多