Firebase数据库快速入门处理的方式是否安全? [英] Is the way the Firebase database quickstart handles counts secure?

查看:127
本文介绍了Firebase数据库快速入门处理的方式是否安全?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我指的是这个链接: https://firebase.google.com/docs/database/android/save-data#save_data_as_transactions


$ b $ (p.stars.containsKey(getUid())在这个例子中,有一个增量字段的代码:

  if ){
//取消星标,从星星中删除自己
p.starCount = p.starCount - 1;
p.stars.remove(getUid());
} else {
//为帖子加星标并将自己添加到stars
p.starCount = p.starCount + 1;
p.stars.put(getUid(),true);
}

但是我怎么能确定用户是否已经喜欢/不喜欢这篇文章?在这个例子中,用户(黑客)可能会像这样清除整个星星图,它将会保存:

  p.stars = new HashMap<>(); 

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



我甚至不认为你可以为此制定规则,特别是对于减少计数操作。

任何帮助,建议? / p>

解决方案

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


  • 确保用户只能将自己的 uid 添加到 stars 节点

     stars:{
    $ uid:{
    .write:$ uid == auth.uid

    }


  • 确保用户只能在将 uid 添加到星号时才能更改 starCount 节点或从那里删除


  • 确保用户只能增加/减少 starCount by 1



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



我发现大多数开发者处理这个问题的方式是:


  • 开始计算客户端(如果 stars >节点的大小不是太大,这是合理的)。
  • 在服务器上运行的可信进程将 stars 集合到 starCount 。它可以使用child_added / child_removed事件递增/递减。

    $ b $ h2更新:与工作示例

    我写了一个投票系统的实例。数据结构是:

    pre code> 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);
    });



    $ b

    它本质上是一个多位置事务,但是内置了应用程序代码和安全规则,而不是Firebase SDK和服务器本身。



    安全规则会执行一些操作:


    1. 确保voteCount只能上升或下降1 /
    2. 确保用户只能添加/删除他们自己的投票



    3. 请注意,规则不会:


      • 确保unvote伴有计数减少(可以使用 .write 规则)
      • 重试失败的投票/ unvotes(处理并发投票/ unvoting)

        $ b $ 规则:

         votes:{
        $ uid:{
        .write:auth.uid = = $ uid,
        .validate:(!data.exists()&& newData.val()== true&& $()$ b $ newData.parent()。parent()。child('voteCount')。val()== data.parent()。parent()。child('voteCount')。val()+ 1


        $ b $ vote_quot:{
        .validate:(newData.val()== data.val()+ 1& amp; ;&
        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用一些代码来测试这个: a href =http://jsbin.com/yaxexe/edit?js,console =noreferrer> http://jsbin.com/yaxexe/edit?js,console


        I want to create an increment field for article likes.

        I am referring to this link: https://firebase.google.com/docs/database/android/save-data#save_data_as_transactions

        In the example there is code for increment field:

        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);
        }
        

        But how can I be sure if the user already liked/unliked the article?

        In the example, user (hacker) might as well clear whole stars Map like this and it will save anyway:

        p.stars = new HashMap<>();
        

        and it will ruin the logic for other users who were already liked it.

        I do not even think you can make rules for this, especially for "decrease count" action.

        Any help, suggestions?

        解决方案

        The security rules can do a few things:

        • ensure that a user can only add/remove their own uid to the stars node

          "stars": {
            "$uid": {
              ".write": "$uid == auth.uid"
            }
          }
          

        • ensure that a user can only change the starCount when they are adding their own uid to the stars node or removing it from there

        • ensure that the user can only increase/decrease starCount by 1

        Even with these, it might indeed still be tricky to have a security rule that ensures that the starCount is equal to the number of uids in the stars node. I encourage you to try it though, and share your result.

        The way I've seen most developers deal with this though is:

        • do the start counting on the client (if the size of the stars node is not too large, this is reasonable).
        • have a trusted process running on a server that aggregates the stars into starCount. It could use child_added/child_removed events for incrementing/decrementing.

        Update: with working example

        I wrote up a working example of a voting system. The data structure is:

        votes: {
          uid1: true,
          uid2: true,
        },
        voteCount: 2
        

        When a user votes, the app sends a multi-location update:

        {
          "/votes/uid3": true,
          "voteCount": 3
        }
        

        And then to remove their vote:

        {
          "/votes/uid3": null,
          "voteCount": 2
        }
        

        This means the app needs to explicitly read the current value for voteCount, with:

        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);
          });  
        }
        

        It's essentially a multi-location transaction, but then built in app code and security rules instead of the Firebase SDK and server itself.

        The security rules do a few things:

        1. ensure that the voteCount can only go up or down by 1
        2. ensure that a user can only add/remove their own vote
        3. ensure that a count increase is accompanied by a vote
        4. ensure that a count decrease is accompanied by a "unvote"
        5. ensure that a vote is accompanied by a count increase

        Note that the rules don't:

        • ensure that an "unvote" is accompanied by a count decrease (can be done with a .write rule)
        • retry failed votes/unvotes (to handle concurrent voting/unvoting)

        The rules:

        "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 with some code to test this: http://jsbin.com/yaxexe/edit?js,console

        这篇关于Firebase数据库快速入门处理的方式是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆