安全规则中的Firebase速率限制?

Bri*_*yer 30 rate-limiting firebase firebase-security firebase-realtime-database

我启动了我的第一个开放式存储库项目EphChat,人们立即开始充斥它的请求.

Firebase是否有办法对安全规则中的限制请求进行评级?我假设有一种方法可以使用请求的时间和先前写入的数据的时间,但在文档中找不到有关如何执行此操作的任何内容.

目前的安全规则如下.

{
    "rules": {
      "rooms": {
        "$RoomId": {
          "connections": {
              ".read": true,
              ".write": "auth.username == newData.child('FBUserId').val()"
          },
          "messages": {
            "$any": {
            ".write": "!newData.exists() || root.child('rooms').child(newData.child('RoomId').val()).child('connections').hasChild(newData.child('FBUserId').val())",
            ".validate": "newData.hasChildren(['RoomId','FBUserId','userName','userId','message']) && newData.child('message').val().length >= 1",
            ".read": "root.child('rooms').child(data.child('RoomId').val()).child('connections').hasChild(data.child('FBUserId').val())"
            }
          },
          "poll": {
            ".write": "auth.username == newData.child('FBUserId').val()",
            ".read": true
          }
        }
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想对整个Rooms对象的db进行速率限制写入(和读取?),因此每秒只能生成1个请求(例如).

谢谢!

Kat*_*ato 42

诀窍是对用户上次发布消息的时间进行审计.然后,您可以根据审计值强制发布每条消息的时间:

{
  "rules": {
          // this stores the last message I sent so I can throttle them by timestamp
      "last_message": {
        "$user": {
          // timestamp can't be deleted or I could just recreate it to bypass our throttle
          ".write": "newData.exists() && auth.uid === $user",
          // the new value must be at least 5000 milliseconds after the last (no more than one message every five seconds)
          // the new value must be before now (it will be since `now` is when it reaches the server unless I try to cheat)
          ".validate": "newData.isNumber() && newData.val() === now && (!data.exists() || newData.val() > data.val()+5000)"
        }
      },

      "messages": {
        "$message_id": {
          // message must have a timestamp attribute and a sender attribute
          ".write": "newData.hasChildren(['timestamp', 'sender', 'message'])",
          "sender": {
            ".validate": "newData.val() === auth.uid"
          },
          "timestamp": {
            // in order to write a message, I must first make an entry in timestamp_index
            // additionally, that message must be within 500ms of now, which means I can't
            // just re-use the same one over and over, thus, we've effectively required messages
            // to be 5 seconds apart
            ".validate": "newData.val() >= now - 500 && newData.val() === data.parent().parent().parent().child('last_message/'+auth.uid).val()"
          },
          "message": {
            ".validate": "newData.isString() && newData.val().length < 500" 
          },
          "$other": {
            ".validate": false 
          }
        }
      } 
  }
}
Run Code Online (Sandbox Code Playgroud)

在这个小提琴中看到它的实际效果.以下是小提琴中的主要内容:

var fb = new Firebase(URL);
var userId; // log in and store user.uid here

// run our create routine
createRecord(data, function (recordId, timestamp) {
   console.log('created record ' + recordId + ' at time ' + new Date(timestamp));
});

// updates the last_message/ path and returns the current timestamp
function getTimestamp(next) {
    var ref = fb.child('last_message/' + userId);
    ref.set(Firebase.ServerValue.TIMESTAMP, function (err) {
        if (err) { console.error(err); }
        else {
            ref.once('value', function (snap) {
                next(snap.val());
            });
        }
    });
}

function createRecord(data, next) {
    getTimestamp(function (timestamp) {
        // add the new timestamp to the record data
        var data = {
          sender: userId,
          timestamp: timestamp,
          message: 'hello world'
        };

        var ref = fb.child('messages').push(data, function (err) {
            if (err) { console.error(err); }
            else {
               next(ref.name(), timestamp);
            }
        });
    })
}
Run Code Online (Sandbox Code Playgroud)

  • 这对仁慈的客户来说非常好。黑客攻击呢?有人不能发布到 last_message 参考。然后,他们可以敲定您的参考资料并一遍又一遍地填写请求。有没有办法提供速率限制来避免这种情况? (4认同)
  • 实际上,我想我会撤回这个.似乎加藤有这个涵盖.您必须发布到last_message或写入"messages"将失败."last_message"通过要求最后一条消息不少于5秒钟来阻止填塞.十分优雅 (4认同)
  • 你正在过度思考这个并且让它变得太复杂,以至于你不会碰到一次性的.如果您的应用程序需要银行级安全性,请编写服务器端进程并让它按下消息,添加您想要的任何级别的限制.或节省一些时间,让您的应用程序发布和使用. (2认同)