Firebase数据库快速入门处理的方式是否安全?

我想为文章喜欢创build一个增量字段。

我指的是这个链接: 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<>(); 

并且会毁掉其他已经喜欢它的用户的逻辑。

我甚至不认为你可以为此制定规则,特别是对于“减less计数”行为。

任何帮助,build议?

安全规则可以做一些事情:

  • 确保用户只能添加/删除自己的stars节点的uid

     "stars": { "$uid": { ".write": "$uid == auth.uid" } } 
  • 确保用户只有在将自己的uid添加到stars节点或将其从中删除时才能更改starCount

  • 确保用户只能增加/减lessstarCount 1

即使有了这些,确实有一个安全规则确保starCount等于stars节点中的uid数量也许还是很棘手的。 我鼓励你尝试一下,分享你的结果。

我看到大多数开发人员处理这个问题的方式是:

  • 开始计算客户端(如果stars节点的大小不是太大,这是合理的)。
  • 在服务器上运行一个受信任的进程,将stars聚合到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. 确保voteCount只能上升或下降1
  2. 确保用户只能添加/删除自己的投票
  3. 确保增加票数的同时进行表决
  4. 确保计数减less是伴随着“unvote”
  5. 确保投票同时增加

请注意,规则不会:

  • 确保“unvote”伴随计数减less(可以使用.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" } 

用一些代码来testing这个jsbin: http ://jsbin.com/yaxexe/edit?js,console