Frage

I was wondering if it were possible to implement some kind of crude JavaScript anti-flood protection. My code receives events from a server through AJAX, but sometimes these events can be quite frequent (they're not governed by me).

I have attempted to come up with a method of combating this, and I've written a small script: 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);
   }
};

which I think could prove effective against these kinds of attacks, but I'm wondering if it can be improved or perhaps rewritten?

So far, I think everything more than 3 or 2.5 lines per second seems like spam, but as time progresses forward (because start mark was set... well... at the start), an offender could simply idle for a while and then commence the flood, effectively never passing 1 line per minute.

Also, I would like to add that I use Mootools and Lo-Dash libraries (maybe they provide some interesting methods), but it would be preferable if this can be done using native JS.

Any insight is greatly appreciated!

War es hilfreich?

Lösung 3

I've spent many days pondering on effective measures to forbid message-flooding, until I came across the solution implemented somewhere else.

First, we need three things, penalty and score variables, and a point in time where last action occured:

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

Next, we decrease score by the distance between the previous message and current in time.

/* 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;

Then we add the message penalty and check if it crosses the threshold:

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

Shouldn't forget to update last action afterwards:

lastact = new Date();

Andere Tipps

If you are concerned about the frequency a particular javascript function fires, you could debounce the function.

In your example, I guess it would be something like:

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

where timeout is the maximum frequency you want someOtherFunction to be called.

I know you asked about native JavaScript, but maybe take a look at RxJS.

RxJS or Reactive Extensions for JavaScript is a library for transforming, composing, and querying streams of data. We mean all kinds of data too, from simple arrays of values, to series of events (unfortunate or otherwise), to complex flows of data.

There is an example on that page which uses the throttle method to "Ignores values from an observable sequence which are followed by another value before dueTime" (see source).

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

There might be a similar way to get your 2.5-3 per second and ignore the rest of the events until the next second.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top