3

我想知道是否有可能实现某种粗略的 JavaScript 防洪泛保护。我的代码通过 AJAX 从服务器接收事件,但有时这些事件可能非常频繁(它们不受我控制)。

我试图想出一种方法来解决这个问题,我写了一个小脚本:http: //jsfiddle.net/Ry5k9/

var puts = {};

function receiverFunction(id, text) {
       if ( !puts[id] ) {
           puts = {};
           puts[id] = {};
       }

       puts[id].start = puts[id].start || new Date();
       var count = puts[id].count = puts[id].count + 1 || 0;
       var time = (new Date() - puts[id].start) * 0.001;

       $("text").set("text", (count / time.toFixed()).toString() + " lines/second");

       doSomethingWithTextIfNotSpam(text);
   }
};

我认为这可以证明对这类攻击有效,但我想知道它是否可以改进或重写?

到目前为止,我认为每秒超过 3 或 2.5 行的所有内容似乎都是垃圾邮件,但随着时间的推移(因为设置了开始标记......好吧......在开始时),违规者可能只是闲置一段时间然后然后开始洪水,实际上每分钟不会超过 1 行。

另外,我想补充一点,我使用 Mootools 和 Lo-Dash 库(也许它们提供了一些有趣的方法),但如果可以使用原生 JS 来完成,那就更好了。

非常感谢任何见解!

4

3 回答 3

1

如果您担心特定 javascript 函数触发的频率,您可以debounce使用该函数。

在你的例子中,我想它会是这样的:

onSuccess: function(){ _.debounce(someOtherFunction, timeOut)}; 

你想被调用timeout的最大频率在哪里。someOtherFunction

于 2013-05-17T09:41:53.193 回答
1

我知道你问过关于原生 JavaScript 的问题,但不妨看看RxJS

RxJS 或 Reactive Extensions for JavaScript 是一个用于转换、组合和查询数据流的库。我们也指各种数据,从简单的值数组到一系列事件(不幸或其他),再到复杂的数据流。

该页面上有一个示例,它使用该throttle方法“忽略来自可观察序列的值,这些值后跟到期时间之前的另一个值”(请参阅​​源代码)。

keyup = Rx.Observable.fromEvent(input, 'keyup').select(function(ev) {
            return ev.target.value;
        }).where(function(text) {
            return text.length > 2;
        }).throttle(500)
        .distinctUntilChanged()

可能有一种类似的方法可以让您每秒获得 2.5-3 次,并在下一秒之前忽略其余事件。

于 2013-05-17T12:10:03.953 回答
1

我花了很多天思考禁止消息泛滥的有效措施,直到我发现在其他地方实施的解决方案。

首先,我们需要三件事,惩罚和得分变量,以及最后一个动作发生的时间点:

var score = 0;
var penalty = 200; // Penalty can be fine-tuned.
var lastact = new Date();

接下来,我们通过前一条消息与当前消息之间的距离来降低分数。

/* The smaller the distance, more time has to pass in order
 * to negate the score penalty cause{d,s}.
 */
score -= (new Date() - lastact) * 0.05; 

// Score shouldn't be less than zero.
score = (score < 0) ? 0 : score;

然后我们添加消息惩罚并检查它是否超过阈值:

if ( (score += penalty) > 1000 ) {
   // Do things.
}

之后不要忘记更新最后一个操作:

lastact = new Date();
于 2013-06-17T16:22:53.123 回答