Rate limiting
New in version 14.2
Previously, the backend and frontend password recovery features, as well as the Extbase rate limiting, each created Symfony rate limiter factories directly, bypassing TYPO3's factory. All consumers now use the central TYPO3 factory, which enables a unified admin override mechanism.
The
\TYPO3\ is available
to serve as the single entry point for all rate limiting across the system.
A new
\TYPO3\ extends
Symfony's
\Symfony\ with
additional convenience methods for request-based and login rate limiting.
Extension developers should type-hint against
Rate when
injecting the factory.
Table of Contents
Overriding the rateLimiter via the TYPO3_CONF_VARS
Example limiter ID for Extbase action
The limiter ID for an Extbase action which uses the
# attribute is constructed using
the "slugified" class name and the action method name.
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\Controller;
use Psr\Http\Message\ResponseInterface;
use TYPO3\CMS\Extbase\Attribute\RateLimit;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
final class MyController extends ActionController
{
#[RateLimit(
limit: 5,
interval: '10 minutes',
message: 'ratelimit.dosomething',
)]
public function doSomethingAction(): ResponseInterface
{
return $this->redirect('index');
}
}
The limiter ID for the action is:
extbase-
General-purpose rate limiting
Extension developers can use the
Rate for custom rate
limiting needs.
The
create method is the recommended entry point for
request-scoped rate limiting. It automatically extracts the client's remote IP
address from the PSR-7 request and uses it as the limiter
key:
<?php
declare(strict_types=1);
namespace MyVendor\MyExtension\RateLimiting;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\RateLimiter\RateLimiterFactoryInterface;
final readonly class MyService
{
public function __construct(
private RateLimiterFactoryInterface $rateLimiterFactory,
) {}
public function doSomething(ServerRequestInterface $request): void
{
$limiter = $this->rateLimiterFactory->createRequestBasedLimiter(
$request,
[
'id' => 'my-extension-action',
'policy' => 'sliding_window',
'limit' => 10,
'interval' => '1 hour',
],
);
$limit = $limiter->consume();
if (!$limit->isAccepted()) {
// handle rate limit exceeded
}
}
}
For cases where a custom key is needed (for example, a user ID instead of the
IP address), the
create method accepts an explicit configuration
array and key:
$limiter = $this->rateLimiterFactory->createLimiter(
[
'id' => 'my-extension-action',
'policy' => 'sliding_window',
'limit' => 10,
'interval' => '1 hour',
],
$userId
);
Pre-configured named services can also be defined in Services.,
which are then injectable with the
create method from the
Rate:
services:
# ... other configuration
myRateLimiter:
class: TYPO3\CMS\Core\RateLimiter\RateLimiterFactory
arguments:
$config:
id: 'my-custom-limiter'
policy: 'sliding_window'
limit: 5
interval: '10 minutes'