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/$uid
和followers/$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
}
}
现在您可以验证以下附加内容:
- 用户只能将自己的UID写入
followers
。 - 用户只有在将其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安全规则,如何保护在其上运行事务的节点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!