Firebase 规则不允许用户删除其他用户的数据

问题描述 投票:0回答:1

我在游戏中使用 firebase,所以我有这个规则:

{
  "rules": {
    ".read": true,
    ".write": "auth != null",
  "users": {
      ".indexOn": ["nickname", "attackPoints"],
      "$uid": {
        "nickname": {
          ".validate": "newData.val().matches(/^[a-zA-Z0-9_]+$/)",
          ".read": true,
          ".write": "$uid === auth.uid"
        },
        "gold": {
          ".read": "$uid === auth.uid",
          ".write": "$uid === auth.uid && newData.isNumber() && ((newData.val() >= 0 && newData.val() <= (data.val() + 1000)) || (data.exists() === false && newData.val() <= 1000))"
        },
        "experience": {
          ".read": "auth != null",
          ".write": "$uid === auth.uid && newData.isNumber() && ((newData.val() >= 0 && newData.val() <= (data.val() + 1000)) || (data.exists() === false && newData.val() <= 1000))"
        },
        "attackPoints": {
          ".read": "auth != null",
          ".write": "$uid === auth.uid && newData.isNumber() && ((newData.val() >= 0 && newData.val() <= (data.val() + 1000)) || (data.exists() === false && newData.val() <= 1000))"
        },
        "characterImageName": {
          ".read": "auth != null",
          ".write": "$uid === auth.uid"
        },
        "work": {
          ".read": "$uid === auth.uid",
          ".write": "$uid === auth.uid"
        },
        "inventory": {
          ".read": "auth != null",
          ".write": "$uid === auth.uid"
        },
                "attacks": {
          "$attackId": {
            ".validate": "newData.child('attacker').val() === auth.uid || newData.child('target').val() === auth.uid || newData.child('target').val() === $uid",
            ".read": "$uid === auth.uid || data.child('attacker').val() === auth.uid",
            ".write": "$uid === auth.uid || newData.child('attacker').val() === auth.uid || newData.child('target').val() === auth.uid"
          }
        }
      }
    }
  }
}

问题是我注意到一个用户(userX)可以删除任何其他用户(userY...)的所有金币。

我尝试删除

".write": "auth != null",
但当新用户尝试在游戏中注册时它会拒绝权限

如有需要,请注册代码:

 val nicknameRef = database.child("users").orderByChild("nickname").equalTo(nick)
nicknameRef.addListenerForSingleValueEvent(object : ValueEventListener {
    override fun onDataChange(snapshot: DataSnapshot) {
        if (snapshot.exists()) {
            // Username is already taken
            showErrorDialog(getString(R.string.username_is_already_taken))
        } else {
            // Username is available, proceed with registration
            auth.createUserWithEmailAndPassword(email, password)
                .addOnCompleteListener(this@Register) { task ->
                    if (task.isSuccessful) {
                        val user = auth.currentUser
                        val userId = user?.uid

                        if (userId != null) {
                            val userData = HashMap<String, Any>()
                            userData["nickname"] = nick
                            userData["experience"] = 0
                            userData["gold"] = 200
                            userData["attackPoints"] = 35
                            userData["characterImageName"] = profile

                            database.child("users").child(userId).setValue(userData)
                                .addOnCompleteListener { dbTask ->
                                    if (dbTask.isSuccessful) {
                                        // Registration and data storage successful
                                        navigateToHome()
                                    } else {
                                        showErrorDialog(
                                            getString(
                                                R.string.error_while_saving_user_data_in_database,
                                                dbTask.exception?.message
                                            ))
                                    }
                                }
                        }
                    } else {
                        showErrorDialog(
                            getString(
                                R.string.registration_error,
                                task.exception?.message
                            ))
                    }
                }
        }
    }

如何避免用户删除其他用户的数据(如金币)并允许新用户注册未经许可拒绝错误?

谢谢

android firebase-realtime-database firebase-security
1个回答
0
投票

Firebase 实时数据库中的读写权限向下级联。这意味着一旦您授予用户某种级别的权限,您就无法在较低级别上取消该权限。

因此,通过这些规则,您实质上是在说世界上的每个人都可以读取整个数据库,并且任何登录的人都可以写入整个数据库:

{
  "rules": {
    ".read": true,
    ".write": "auth != null",
    ...

无论规则中其他地方有什么读/写规则,它们都不能覆盖这些顶级规则。有关这方面的更多信息,请参阅文档中的读写规则级联


因此,如果您不希望所有用户都能够在数据库中的任何位置进行写入,则必须删除该顶级写入规则。

我尝试删除“.write”:“auth!= null”,但当新用户尝试在游戏中注册时,它会拒绝权限

这意味着您现在缺少一条规则,该规则允许您在新用户在游戏中注册时执行写入操作。如果该操作对应于以下代码:

database.child("users").child(userId).setValue(userData)

然后您需要实际授予用户对该确切路径的写入权限。所以:

"users": {
  ".indexOn": ["nickname", "attackPoints"],
  "$uid": {
    ".write": "auth !== null && auth.uid === $uid",
    ...

因此,通过此规则,如果

/users/$uid
变量对应于他们自己的 UID(在您的代码中这样做),用户可以写入
userId
路径。

有关此内容的更多信息,另请参阅有关 仅保护内容所有者访问的 Firebase 文档。

© www.soinside.com 2019 - 2024. All rights reserved.