randomKek
randomKek

Reputation: 1128

PHP request spam prevention mechanism

I'm building a model view controller web application and I want to build a request spam mechanism, why? Let me explain in short detail:

We got ourselves an ajax controller, every user input is received through ajax, no direct $_POST is done in my web application.

Let's imagine a few actions of the Ajax controller where we want to put a spam prevention mechanism on:

class AjaxController{
    private function setPrevention($interval){
        $latestActionRequest = $_SESSION['requests'][$this->action];

        if($prevention === null){
            $_SESSION['requests'][$this->action] = array('latest' => microtime(), 'interval' => $interval
        } else {
            // Calc difference here, and check if the interval was within range, else
            // the user was requesting the action method to quickly.
        }
    }

    public function _postComment(){
        $this->setPrevention(1000);

        // Apply validation, on the $_POST array, insert the to database.
    }
}

So we got an action to post a comment, we only want to allow the user to post a comment each second, so we apply a very basic prevention mecanisch in our session.

Check the comment in the setPrevention method. I have got 2 questions, my first question is, is this mechanism a good idea? Or are there alternative better ways to build this?

Second question is, how do I check if the latest request was within the interval range? With microtime - microtime I get the difference in seconds, but there are actions where I want to apply an 500 ms interval.

What I got so far:

$_SESSION['requests']['postComment'] = array('latest' => microtime(true), 'interval' => 1000);
$difference = ($_SESSION['requests']['postComment'] - microtime(true));

At this point $difference gives back float(106.984388113) (waited 106 seconds) But we want to get the microtime difference because our interval is 1000 (which is 1 second not 1000)

I hope my question was clear, thanks for help.

Upvotes: 1

Views: 436

Answers (2)

CLo
CLo

Reputation: 3730

The first answer should help with the sub second timing. microtime(true)

In response to the edit: The decimal portion is the sub second timing. the .984 is the part you're looking for in terms of precision. .500 is your 500 milliseconds. I would recommend setting up your intervals in terms of this float value.

You could multiply the difference by 1000, but if you ever want to adjust to a precision greater or less than milliseconds it'll be even more confusing. And I propose making it as easy to adjust this later as you can.

As for the mechanism for spam prevention there are a lot of options, but they will depend on the specifics of what your application needs.

The best advice I could give you for that is to abstract it in some way that it can get more information about the AJAX call than you think you may need now and build a simple system that works now and log the information about requests for review.

The biggest problem with spam prevention is preventing legitimate users and annoying them. So the best thing you can do is make it easier for yourself or another developer to swap out your mechanism in the future. You also need to have logs of the requests to be able to determine what kinds of requests are being stopped or not by the spam prevention.

Upvotes: 1

Francois Deschenes
Francois Deschenes

Reputation: 24989

If you use microtime(true) instead of just microtime(), it'll return a float instead of a string. Using the float, you'll be able to calculate the number of milliseconds elapsed since the original request.

Make sure to use microtime for both the start and end time.

As for the other question, this is definitely one way you can limit the number of requests. There may be other ways too and that question isn't really what Stack Overflow was designed for. It's subjective.

Upvotes: 1

Related Questions