Anti-automation is a key security feature when building a new application. It is the ability to block suspicious traffic from the outside, for example from a malicious user that tries to DoS your website by opening it like 1000 times in a minute using an automated tool (for example Apache jMeter or wrk).
There are many providers such as Cloudflare which has set of tools to avoid these kind of attacks, but sometimes it is not possible to use an external service. Clearly, these providers will bring you many security features that are hard to build from scratch (nearly impossible), but it is important to know at least the basics security informations to choose which is the better for your case and to understand how to implement a simple security system.
I suggest to see the OWASP Top Ten, a standard for Web security that gives 10 fundamental principles every web app should have.
In the OWASP Top Ten, Anti-Automation is included in the category A04 Insecure Design.
Here we explore how to handle anti-automation on the application layer (i.e. the web app, in our case based on Laravel), but there are many solutions. For example, if possible, I suggest to use a Web Application Firewall (WAF) with a mechanism for anti-automation, or implement it on your web server (for example, there is a tutorial for NGINX).
Implementing it on your web app is important because there could be different limits based on your needs. For example, on NGINX you set that an IP could access your web app at most 100 times in a minute, but you want to limit the APIs on 70 times in a minute and the website homepage on 30 times in a minute. In such cases, the customization is difficult using a WAF or a web server.
In general, there should be a minimum of two anti automation mechanism:
one on the WAF or Web Server, and one on the application
Tutorial
It’s time to start. We will use the Laravel built-in rate limiter feature, and our goal is to permit to every IP to access at most 50 times our website in a minute.
Let’s make a middleware:
php artisan make:middleware AntiAutomationMiddleware
Add it into the Kernel.php
file:
protected $routeMiddleware = [
// other middlewares ...
'anti_automation' => AntiAutomationMiddleware::class,
];
Let’s add it into your routes by adding a trailing →middleware(‘anti_automation’);
The middleware is configured to work on selected routes, and now it is the time to implement its handle method.
This is what it will be:
public function handle(Request $request, Closure $next): Response
{
$key = 'anti-automation:' . $request->ip();
if (RateLimiter::tooManyAttempts($key, 50)) {
return response('<h1>Too Many Requests</h1>', 429)
->header('Content-Type', 'text/html');
}
RateLimiter::hit($key, 60);
return $next($request);
}
Here, a new key is created for the rate limiter. The name is anti-automation:[REQUEST_IP]
, but it can be everything you want.
For example if it became something like ‘anti-automation:’ . auth()→id()
, the rate limiter will be applied on the authenticated user.
After that, if the rate limiter reached 50 attempts, it will return a response containing <h1>Too Many Requests</h1>
with a 429
status code (corresponding to Too Many Requests). It is possible to change the behaviour, but I’m leaving a simple error message that doesn’t trigger exceptions.
Finally, it does a simple +1 on the attempts for the given key, with a validity of 60 seconds (second parameter, called decaySeconds
).
✅ Congratulations! You implemented a simple anti automation in your Laravel app. If you liked this article and you want more, subscribe (with free tier) using the following button.