使用Firebase安全规则,如何保护在其上运行事务的节点? [英] Using Firebase Security Rules, how can I secure a node that has transactions run on it?

本文介绍了使用Firebase安全规则,如何保护在其上运行事务的节点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的数据库中,我有一个用户节点,其中包含一个用户ID下的数据。 这包括他们的简历、关注者数量、用户是否为版主等。

users
{
    userId1
    {
        bio: "Example bio..."
        followers: 250
        moderator: true
        ...
    }
}
为了使关注者的数量正确,我使用transaction block在每次单击Follow按钮时递增关注者属性。还有一些其他属性也需要事务块。

不幸的是,我发现为了使事务工作,必须将$USERID节点的安全规则设置为:".write": "auth != null"。否则,当有人单击"关注"按钮时,"关注者数量"属性不会增加。因为事务块查询整个用户,所以我们不能将安全规则限制为仅"Followers"属性。

"users":
{
     "$userId": 
     {
        // Has to be set like this or transactions won't work
        ".read": "auth != null",
        ".write": "auth != null",


        "bio":
        {
            // This will have no effect due to rule cascading
            ".write": "auth.uid === $userId"
        }

        "moderator":
        {
            // This will have no effect due to rule cascading
            ".write": ...
        }
    }
}

由于规则级联,这使得无法为User下的任何其他属性设置特定规则,包括个人简介和用户是否为版主等。这使得恶意用户很容易更改User属性。

发布和点赞也会发生同样的事情,即Firebase文档中使用的示例。因为事务块查询整个帖子,所以我们不能将安全规则仅限于"Like"属性。由于级联,所有其他POST属性将不得不满足".write": "auth !=null"设置。

我最多只能使用验证,但这不能阻止恶意用户将他们的关注次数设置为10,000,或者在他们以某种方式获得访问权限时使自己成为版主。

使用Firebase规则,是否有办法保护运行事务的节点?


编辑:更多信息

这是我的事务块的简化版本,用于增加关注者计数:

    // Run transaction block on the user in the "users" node
    userRef.runTransactionBlock({ (currentData: MutableData) -> TransactionResult in

        // Store the user 
        if var user = currentData.value as? [String: AnyObject]
        {
            // Get the number of followers
            var numberOfFollowers = user["numberOfFollowers"] as? Int ?? 0

            // Increase the number of followers by 1
            numberOfFollowers += 1


            // Set the new number of followers
            user["numberOfFollowers"] = numberOfFollowers as AnyObject?

            // Set the user value and report transaction success
            currentData.value = user

            return TransactionResult.success(withValue: currentData)
        }

        return TransactionResult.success(withValue: currentData)
    })

关注者在我的数据库中的存储方式如下:

myDatabase: {
    followers: {
        "andrew098239101": {
            // These are all the user ID's of users that follow "andrew098239101"
            "robert12988311": true
            "sarah9234298347": true
            "alex29101922": true
            "greg923749232": true
        }
        "robert12988311": {
            "alex29101922": true
        }
    }
    ...
    users: {
        "andrew098239101": {
             // Andrew's user info
             "bio": "hello I am Andrew"
             "numberOfFollowers": 4
             "moderator": true
             ...
        }
        "robert12988311": {
             "bio": "I'm Robert"
             "numberOfFollowers": 1
             "moderator": false
             ...
        }
    }
}

有一个类似的节点用于跟随,等等。

推荐答案

您应该只能在followers属性上设置较宽松的写入权限。所以大概是这样的:

"users": {
     "$userId":  {
        ".read": "auth != null",
        ".write": "auth.uid === $userId",
        "followers": {
            ".write": "auth.uid !== null"
        },
    }
}

这样,所有经过身份验证的用户都可以写入/users/$uid/followers,但只有配置文件的所有者可以写入其他值。


我建议将followers与其他用户配置文件数据分开,以便您有两个顶级列表:users/$uidfollowers/$uid,其中users/$uid包含只有所有者可以写入的用户配置文件,followers/$uid包含关注者可以写入的数据。


我还建议不仅存储计数,还存储他们的关注者的UID。事实上,我会使用这个结构:

users: {
  "uidOfMichael": {
    followers: {
      "uidOfFrank": true,
      "uidOfJames": true,
      "uidOfAndrew": true
    },
    followerCount: 3
  },
  "uidOfFrank": {
    followers: {
      "uidOfJames": true,
      "uidOfAndrew": true
    },
    followerCount: 2
  },
  "uidOfJames": {
    followers: {
      "uidOfAndrew": true
    },
    followerCount: 1
  },
  "uidOfAndrew": {
    followers: {
      "uidOfJames": true
    },
    followerCount: 1
  }
}

现在您可以验证以下附加内容:

  1. 用户只能将自己的UID写入followers
  2. 用户只有在将其UID添加到followers时才能递增followerCount

规则如下(可能有打字错误):

"users": {
     "$userId":  {
        ".read": "auth != null",
        ".write": "auth.uid === $userId",
        "followers": {
            "$followerId": {
                ".write": "auth.uid !== $followerId"
            }
        },
        "followerCount": {
            ".write": "
              newData.val() === data.val() + 1 &&
              !data.parent().child('followers').child(auth.uid).exists() &&
              newData.parent().child('followers').child(auth.uid).exists()
            "
        }
    }
}

这篇关于使用Firebase安全规则,如何保护在其上运行事务的节点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆