我指的是这个链接:https://firebase.google.com/docs/database/android/save-data#save_data_as_transactions
在示例中有增量字段的代码:
if (p.stars.containsKey(getUid())) { // Unstar the post and remove self from stars p.starCount = p.starCount - 1; p.stars.remove(getUid()); } else { // Star the post and add self to stars p.starCount = p.starCount + 1; p.stars.put(getUid(),true); }
在这个例子中,用户(黑客)可能会清楚整个星星这样的地图,它会保存:
p.stars = new HashMap<>();
并会破坏其他已经喜欢的用户的逻辑.
我甚至不认为你可以为此制定规则,特别是对于“减少计数”行动.
任何帮助,建议?
解决方法
"stars": { "$"uid": { ".write": "$uid == auth.uid" } }
>确保用户只能在将星号添加到星形节点或从其中删除时更改starCount
确保用户只能将StarCount增加/减1
即使有了这些,有一个安全规则确实可以确保starCount等于星形节点中的uid数量的确仍然是棘手的.我鼓励你尝试它,并分享你的结果.
我看到大多数开发人员处理的方式是:
>在客户端开始计数(如果星星节点的大小不是太大,这是合理的).
>在服务器上运行受信任的进程,将星星聚合到starCount中.它可以使用child_added / child_removed事件来递增/递减.
更新:以工作为例
我写了一个投票系统的工作示例.数据结构如下:
votes: { uid1: true,uid2: true,},voteCount: 2
当用户投票时,应用程序会发送多位置更新:
{ "/votes/uid3": true,"voteCount": 3 }
然后删除他们的投票:
{ "/votes/uid3": null,"voteCount": 2 }
这意味着应用程序需要显式地读取当前的voteCount值,其中:
function vote(auth) { ref.child('voteCount').once('value',function(voteCount) { var updates = {}; updates['votes/'+auth.uid] = true; updates.voteCount = voteCount.val() + 1; ref.update(updates); }); }
它本质上是一个多位置事务,但是内置了应用程序代码和安全规则,而不是Firebase SDK和服务器本身.
安全规则做了一些事情:
>确保投票数只能上升或下降1
>确保用户只能添加/删除自己的投票
>确保计数增加伴随投票
>确保计数减少伴随着“不投票”
>确保投票伴随着增加计数
请注意,规则不:
>确保“unvote”伴随着减少计数(可以用.write规则完成)
>重试失败投票/非投票(处理并发投票/取消投票)
规则:
"votes": { "$uid": { ".write": "auth.uid == $uid",".validate": "(!data.exists() && newData.val() == true && newData.parent().parent().child('voteCount').val() == data.parent().parent().child('voteCount').val() + 1 )" } },"voteCount": { ".validate": "(newData.val() == data.val() + 1 && newData.parent().child('votes').child(auth.uid).val() == true && !data.parent().child('votes').child(auth.uid).exists() ) || (newData.val() == data.val() - 1 && !newData.parent().child('votes').child(auth.uid).exists() && data.parent().child('votes').child(auth.uid).val() == true )",".write": "auth != null" }
jsbin用一些代码来测试这个:http://jsbin.com/yaxexe/edit?js,console