Firebase在安全规则中的速率限制? [英] Firebase rate limiting in security rules?

查看:194
本文介绍了Firebase在安全规则中的速率限制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我启动了我的第一个开放存储库项目, EphChat ,人们迅速开始提出请求。 / p>

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



  {
rules:{
房间:{
$ RoomId:{
connections:{
.read:true,
.write:auth.username == newData .child('FBUserId')。val()
},
messages:{
$ any:{
.write:!newData。存在()|| 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.chi ('RoomId').val())。child('connections')。hasChild(data.child('FBUserId').val())
}
},
poll:{
.write:auth.username == newData.child('FBUserId')。val(),
.read:true
}



$ b code


想要限制写入(和读取?)到整个房间对象的数据库,所以每秒只能有一个请求(例如)。



谢谢!

解决方案

诀窍是保持上次用户发布消息的审计。然后,您可以根据审计值强制执行每封邮件的发布时间:

  {
rules:{
//这存储了我发送的最后一条消息,所以我可以通过时间戳
last_message来节制它们:{
$ user:{
// timestamp can not be删除或我可以只是重新创建它绕过我们的油门
.write:newData.exists()&& auth.uid === $ user,
//新值必须在最后(不超过一个消息每五秒钟)至少5000毫秒
//新的值必须在现在之前(这将是因为现在是当它到达服务器,除非我试图作弊)
.validate:newData.isNumber()& newData.val()=== now&&(!data.exists()|| newData.val()> data .val()+ 5000)

},

messages:{
$ message_id:{
// message must有一个时间戳属性和一个发件人属性
.write:newData.hasChildren(['timestamp','sender','message']),
sender:{
.validate: newData.val()=== auth.uid

timestamp:{
//为了编写消息,我必须先在timestamp_index
//此外,该消息必须在500毫秒之内,这意味着我不能
//只是重复使用同一个,因此,我们已经有效地要求消息
//相隔5秒
.validate:newData.val()> = now - 500&& newData.val()=== data.parent()。parent()。parent()。child('last_message /'+ auth.uid).val()
},
:{
.validate:newData.isString()&& newData.val()。length< 500

$ other:{
.validate:false
}
}
}
}

$ / code>

请参阅在这个小提琴。这是什么在小提琴的要点:$ b​​
$ b

  var fb = new Firebase(URL); 
var userId; //在这里登录并存储user.uid

//运行我们的create例程
createRecord(data,function (recordId,timestamp){
console.log('created record'+ recordId +'at time'+ new Date(timestamp));
});

//更新last_message /路径并返回当前时间戳
函数getTimestamp(next){
var ref = fb.child('last_message /'+ userId);
ref.set(Firebase.ServerValue如果(err){console.error(err);}
else {
ref.once('value',function(snap){
下一个(snap.val());
});
}
});


函数createRecord(data,next){
getTimestamp(函数(timestamp)){
//将新的时间戳添加到记录数据
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(),时间戳);
}
});
})
}


I launched my first open repository project, EphChat, and people promptly started flooding it with requests.

Does Firebase have a way to rate limit requests in the security rules? I assume there's a way to do it using the time of the request and the time of previously written data, but can't find anything in the documentation about how I would do this.

The current security rules are as follows.

{
    "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
          }
        }
      }
    }
}

I would want to rate-limit writes (and reads?) to the db for the entire Rooms object, so only 1 request can be made per second (for example).

Thanks!

解决方案

The trick is to keep an audit of the last time a user posted a message. Then you can enforce the time each message is posted based on the audit value:

{
  "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 
          }
        }
      } 
  }
}

See it in action in this fiddle. Here's the gist of what's in the fiddle:

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

这篇关于Firebase在安全规则中的速率限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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