首页 > 解决方案 > 在 Firebase 实时数据库规则中,您如何为具有特定子值的用户授予写入权限?

问题描述

,"people" : {
  ".read": "auth != null",
  "$uid":  {
  },
  "e2" : {     
    ".read": "auth.uid != null",
    ".write": "$uid == auth.uid"  
  },
  "l1" : {     
    ".read": "auth.uid != null",
    ".write": "auth.uid != null"  
  }

所以 e2 是电子邮件的@。例如@gmail 或@aol 或@yahoo。对于 l1 孩子,我想制定写规则:写 if auth.uid != null && e2 与你正在写 l1 的人的 e2 具有相同的值。我能得到的最远的是这样的:

"data.parent().child(people).hasChildren(['auth.uid', 'l1'])"    

JSON

"people": {
    "02PdiNpmW3MMyJt3qPuRyTpHLaw2": {
        "e2": "aol.com",
        "l1": 4,
        "X": {
            "e2": "aol.com",
            "l1": 0,
            "P": {
                "e2": "gmail.com",
                "l1": 0,

基本上 l1 = like,所以一个用户以将计数加 1 的形式写入另一个用户的 l1。

应该成功的操作:

用户 X 想要喜欢 uid 为 02PdiNpmW3MMyJt3qPuRyTpHLaw2 的用户。用户 X 有一个 @aol.com 的 e2 子级。这与他想要喜欢的用户的e2孩子相同。用户 x 也是授权用户,因此他满足 2 个要求来写他想要喜欢的用户的 l1。

不应该成功的操作:

用户 P 想要喜欢 uid 为 02PdiNpmW3MMyJt3qPuRyTpHLaw2 的用户。用户 P 有一个 @gmail.com 的 e2 子级。这和他想要喜欢的用户的e2孩子不一样。因此,用户 P 不满足写给他想要喜欢的用户的 l1 的要求

标签: firebasefirebase-realtime-databasefirebase-authenticationfirebase-security

解决方案


这是一个非常复杂的场景,所以我将逐步介绍它。您很有可能需要进行更改以使这些规则适用于您的完整用例,因此我希望每个步骤都可以让您自己调整它们。


第一步是去混淆你的数据结构。我将改为使用此结构开始:

{
  "people" : {
    "user1" : {
      "domain" : "aol.com",
      "likeCount" : 2,
      "likers" : {
        "user2" : {
          "comain" : "aol.com"
        },
        "user3" : {
          "domain" : "aol.com"
        }
      }
    }
  }
}

所以user1有两个喜欢,来自user2user3一个域。

强烈建议在您的数据库中使用像这样有意义的名称,但绝对是在您发布的有关它的问题中。如果人们不能轻易理解您的数据模型,那么他们提供帮助的机会就会迅速下降。


在上述数据模型中,我们可以确保只有来自同一域的用户可以通过以下方式点赞该用户:

  "people": {
    "$uid": {
      "likers": {
        "$likerid": {
          ".write": "data.parent().parent().child('domain').val() == newData.child('domain').val()"
        }
      }
    }
  }

有了这些规则,我尝试了两次对people/user1/likers/user4. 第一个操作成功:

{
  "domain": "aol.com"
}

第二个操作失败:

{
  "domain": "gmail.com"
}

我们可能还应该确保用户只能写自己喜欢的内容,而不能写给其他用户。我们可以这样做:

  "people": {
    "$uid": {
      "likers": {
        "$likerid": {
          ".write": "$likerid == auth.uid && 
            data.parent().parent().child('domain').val() == newData.child('domain').val()"
        }
      }
    }
  }

接下来,我们将添加一个规则,允许用户喜欢某人,前提是他们以前没有喜欢过某人。我们将继续这样做,因为people/$uid我们需要很快查看数据。likerslikesCount

第一步的规则是:

  "people": {
    "$uid": {
      ".write": "
        !data.child('likers').child(auth.uid).exists() && newData.child('likers').child(auth.uid).exists()
      ",
      "likers": {
        "$likerid": {
          ".write": "$likerid == auth.uid && 
            data.parent().parent().child('domain').val() == newData.child('domain').val()"
        }
      }
    }

因此,如果我们要添加尚不存在的类似内容,这些规则允许我们向用户写信。您可能需要在此处进行额外检查以允许更新其他子节点,但在这里我们将保持尽可能简单(因为它已经非常复杂了)。


最后,您要确保写入还必须增加likeCount,这应该是这样的:

  "people": {
    "$uid": {
      ".write": "
        !data.child('likers').child(auth.uid).exists() && newData.child('likers').child(auth.uid).exists()
        && newData.child('likeCount').val() == data.child('likeCount').val() + 1
      ",
      "likers": {
        "$likerid": {
          ".write": "$likerid == auth.uid && 
            data.parent().parent().child('domain').val() == newData.child('domain').val()"
        }
      }
    }

所以新行现在检查新数据likeCount是否比之前的值高一个。


我已经在自己的测试数据库中采取了上述每个步骤,并在操场上测试了正面和负面案例。因此,虽然可能存在一些问题,但每个步骤的基本方法都有效。

如前所述,这非常复杂,您很可能需要进行重大更改才能完全适用于您的所有用例。


推荐阅读