我在游戏中使用 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
))
}
}
}
}
如何避免用户删除其他用户的数据(如金币)并允许新用户注册未经许可拒绝错误?
谢谢
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 文档。