【问题标题】:JavaScript anti-flood spam protection?JavaScript 反泛滥垃圾邮件保护?
【发布时间】:2013-05-17 09:30:13
【问题描述】:

我想知道是否有可能实现某种粗略的 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 来完成,那就更好了。

非常感谢任何见解!

【问题讨论】:

  • 如果有人向网站发送垃圾邮件,他们可能没有使用浏览器来执行此操作(即他们完全绕过了 JavaScript)。在任何情况下,如果有人将文本复制粘贴到输入字段,您的方法要么崩溃,要么认为他们正试图淹没网站。
  • @Juhana:但我正在从服务器接收事件(我无法控制)。
  • 那我真的不明白你在做什么,对不起。如果事件来自服务器,试图捕获的 keydown 事件是什么?
  • 我使用 keydown 只是为了说明我的意思,它可能是一个简单的函数(实际上是 Mootools 的 onSuccess 函数)。也许我并不清楚,应该改变它。
  • 如果您使用的是 AJAX,那么您是在请求事件,而不是接收它们。你在说什么洪水?

标签: javascript spam-prevention


【解决方案1】:

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

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

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

其中timeout 是您希望调用someOtherFunction 的最大频率。

【讨论】:

  • onSuccess 我使用的函数非常复杂,并且取决于每个单独函数的返回输出(事件类型,例如“已连接”、“已断开”等)。检查源代码,似乎去抖动它会返回“最后一个 func 调用的结果”,这可能会破坏已经脆弱的代码。
  • “已经脆弱的代码”? - 听起来像是重构时间... :)
  • @ma_il:哈哈,也许吧。我必须重新发明一切,“如果它有效,就不要修复它”在这里有点适用。
  • 啊,很公平,您可以按类型分别对每个事件进行去抖动?
【解决方案2】:

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

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

该页面上有一个示例,它使用throttle 方法来“忽略来自可观察序列的值,这些值在dueTime 之前跟随另一个值”(请参阅​​source)。

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 次,并在下一秒之前忽略其余事件。

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-22
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 2012-05-15
      • 1970-01-01
      • 2014-05-19
      • 2013-10-02
      相关资源
      最近更新 更多