【问题标题】:Firebase Realtime Rules: Allowing multiple Users Access to DataFirebase 实时规则:允许多个用户访问数据
【发布时间】:2021-05-02 01:10:40
【问题描述】:

所以我的数据库结构是这样的,所有者在创建组时设置,所有者应该有权添加其他用户以允许他们也可以访问和编辑数据。

-Groups
   |-Groupname
      |- Owner: string
      |- Allowed: List<string>
      |- Data: all the data

所以我的尝试是这些规则,但是当我使用游乐场功能并在所有者或允许下保存 uid 时它们不起作用:

"Groups" : {
      "$group": {
        ".read": "auth != null && (data.child('Owner').val() === auth.uid || data.child('Allowed').val() === auth.uid)",
        ".write": "auth != null && (data.child('Owner').val() === auth.uid || data.child('Allowed').val() === auth.uid)"
                }
           }

当这些规则有效时,用户是否仍然能够创建新组? 数据库和错误的图片:

【问题讨论】:

  • 您能否编辑您的问题以显示操场的屏幕截图,显示您尝试过的内容、遇到的错误以及与规则相关的数据?
  • 成功了!如果您需要更多或澄清,请问我!
  • 你不应该在操场上的 UID 值周围有"s。
  • 对不起,我草率地复制它仍然返回相同的错误,没有它们

标签: firebase-realtime-database firebase-security


【解决方案1】:

首先,在实时数据库中,avoid using arrays 并改用地图。

改变这个:

"Allowed": {
  "0": "8ZiQGBPFkiZOLgLJBgDeLw9ie9D3",
  "1": "KEuhrxnAWXS0dnotjhjFAYUOcm42",
  "2": "48yULftKSxgyS84ZJC4hs4ug4Ei2"
}

到这里:

"Allowed": {
  "8ZiQGBPFkiZOLgLJBgDeLw9ie9D3": true,
  "KEuhrxnAWXS0dnotjhjFAYUOcm42": true,
  "48yULftKSxgyS84ZJC4hs4ug4Ei2": true
}

阅读链接的博客文章了解更多信息,但简而言之,它使添加/删除用户变得非常简单:

const groupRef = firebase.database.ref(`Groups/${groupId}`);

// add a user
groupRef.child("E04HLbIjGDRUQxsRReHSKifaXIr2").set(true);

// remove a user
groupRef.child("KEuhrxnAWXS0dnotjhjFAYUOcm42").remove();

您还可以将true 更改为您想要的任何内容。下面是一些例子:

  • false = 参与者,true = 主持人
  • false = 只读,true = 可以编辑
  • 角色名称:"member""admin""moderator"
  • 权限级别:0(成员)、500(版主)、1000(所有者)等(确保将它们分开,您不希望在两者之间添加一个级别01 并且必须编辑您的整个数据库)。

不过,最重要的一点是实时数据库安全规则不了解数组。 data.val() 不会返回数组,它只会返回一个标记值,上面写着“非空对象在这里!”。这意味着安全规则需要地图。

This reference document 涵盖了您可以在实时数据库安全规则中使用的结构和变量。

根据您提议的规则,您尝试允许组中的任何用户都能够写入组的数据 - 但您无法管理他们可以写入和不可以写入的内容。群组中的任何恶意成员都可以添加/删除其他任何人,使自己成为所有者,甚至完全删除群组。

{
  "rules": {
    "Groups" : {
      "$group": {
        // If this group doesn't exist, allow the read.
        // If the group does exist, only the owner & it's members
        // can read this group's entire data tree.
        ".read": "!data.exists() || (auth != null && (data.child('Owner').val() === auth.uid || data.child('Allowed').child(auth.uid).val() === true))",

        "Owner": {
          // Only the current owner can write data to this key if it exists.
          // If the owner is not yet set, they can only claim it for themselves.
          ".write": "auth != null && (data.val() === auth.uid || (!data.exists() && newData.val() === auth.uid))",

          // Force this value to be a string
          ".validate": "newData.isString()"
        },

        "Allowed": {
          // Only the owner can edit the entire member list
          // For a new group, the owner is also granted write access
          // for it's creation
          ".write": "auth != null && (data.parent().child('Owner').val() === auth.uid || (!data.exists() && newData.parent().child('Owner').val() === auth.uid))",

          "$member": {
            // Allows the user to remove themselves from the group
            ".write": "auth != null && auth.uid === $member && !newData.exists()",

            // Force this value to be a boolean
            ".validate": "newData.isBoolean()"
          }
        },

        "Data": {
          // The owner and members can edit anything under "Data"
          // Currently this includes deleting everything under it!
          // For a new group, the owner is also granted write access
          // for it's creation
          // TODO: tighten structure of "Data" like above
          ".write": "auth != null && (data.parent().child('Owner').val() === auth.uid || data.parent().child('Allowed').child(auth.uid).val() === true || (!data.exists() && newData.parent().child('Owner').val() === auth.uid))"
        }
      }
    }
  }
}

【讨论】:

  • 所以我对这个很陌生,感谢您的洞察力!当您谈到地图时,我可以使用字典(c#)还是基本上是一样的?因为正如您所说,目前我正在使用列表。明天我会尝试实现它。给你解决。如果我有任何问题,我会发表评论。
  • 正确。对于这种类型的映射C#,您将使用IDictionary{string, bool}
  • 所以像这样实现它,它就像一个魅力!感谢您提供所有信息!
  • 如何查询用户有权访问的所有组?您需要对所有组进行单独查询吗?
  • @SimonTran 你最好的选择是建立一个“userId->groupId=true”索引。每个用户都将他们的组存储在/GroupMembership/{userId} 下,就像您将用户ID 存储在Allowed 下一样(即/GroupMembership/{userId}/{someGroupId} = true)。要获取该用户组,您只需下拉/GroupMembership/{userId}。虽然您可以直接查询/Groups 下的数据,但它需要下载所有数据才能进行筛选 - 这很慢,效率低,并且会导致处理权限问题。
猜你喜欢
  • 1970-01-01
  • 2020-06-09
  • 1970-01-01
  • 2019-09-24
  • 2017-03-10
  • 2018-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多