【发布时间】:2021-02-24 19:29:22
【问题描述】:
在我的数据库中,我有一个用户节点,其中包含用户 ID 下的数据。 这包括他们的个人简介、关注者数量、用户是否是版主等等。
users
{
userId1
{
bio: "Example bio..."
followers: 250
moderator: true
...
}
}
为了使关注者的数量正确,我使用transaction block 在每次点击关注按钮时增加关注者属性。还有一些其他属性也需要事务块。
不幸的是,我发现为了使交易正常工作,$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": ...
}
}
}
而且由于规则级联,这使得为用户下的任何其他属性设置特定规则似乎是不可能的,包括 bio 以及用户是否是版主等。这使得用户属性容易受到恶意用户的更改。
同样的事情发生在帖子和点赞上,Firebase 文档中使用的示例。因为事务块查询整个帖子,我们不能将安全规则限制为“likes”属性。由于级联,所有其他帖子属性都必须适应“.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
...
}
}
}
有一个类似的节点用于关注等
【问题讨论】:
-
“每次点击关注按钮时,我都会使用事务块来增加关注者属性”我实际上建议使用
ServerValue.increment(1),因为它将是more efficient。不过,它不应该对您询问的安全规则产生影响,因为它仍然是同一个用户编写的。 -
谢谢,我试试 ServerValue.increment(1) 看看有没有效果
-
您能否确保您发布的数据结构是有效的 JSON?无法存储您在 Firebase 实时数据库中发布的最后一个结构,而实际结构对于如何保护它(以及这是否可能)很重要。
-
感谢您更新您的答案,我更新了数据库示例以更清晰。
标签: swift firebase firebase-realtime-database firebase-authentication firebase-security