src/Eccube/EventListener/RateLimiterListener.php line 41

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Eccube\EventListener;
  13. use Eccube\Common\EccubeConfig;
  14. use Eccube\Entity\Customer;
  15. use Eccube\Entity\Member;
  16. use Eccube\Request\Context;
  17. use Psr\Container\ContainerInterface;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. use Symfony\Component\HttpKernel\Event\ControllerEvent;
  20. use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
  21. use Symfony\Component\HttpKernel\KernelEvents;
  22. use Symfony\Component\RateLimiter\RateLimiterFactory;
  23. use Symfony\Component\Security\Core\User\UserInterface;
  24. class RateLimiterListener implements EventSubscriberInterface
  25. {
  26.     private ContainerInterface $locator;
  27.     private EccubeConfig $eccubeConfig;
  28.     private Context $requestContext;
  29.     public function __construct(ContainerInterface $locatorEccubeConfig $eccubeConfigContext $requestContext)
  30.     {
  31.         $this->locator $locator;
  32.         $this->eccubeConfig $eccubeConfig;
  33.         $this->requestContext $requestContext;
  34.     }
  35.     public function onController(ControllerEvent $event)
  36.     {
  37.         if (!$event->isMainRequest()) {
  38.             return;
  39.         }
  40.         $request $event->getRequest();
  41.         $route $request->attributes->get('_route');
  42.         $limiterConfigs $this->eccubeConfig['eccube_rate_limiter_configs'];
  43.         if (!isset($limiterConfigs[$route])) {
  44.             return;
  45.         }
  46.         $method $request->getMethod();
  47.         foreach ($limiterConfigs[$route] as $id => $config) {
  48.             $methods array_filter($config['method'], fn ($m) => $m === $method);
  49.             if (empty($methods)) {
  50.                 // http methodが不一致であればスキップ
  51.                 continue;
  52.             }
  53.             if (!empty($config['params'])) {
  54.                 $matchParams array_filter($config['params'], function ($value$key) use ($request) {
  55.                     return $request->get($key) === $value;
  56.                 }, ARRAY_FILTER_USE_BOTH);
  57.                 if (count($config['params']) !== count($matchParams)) {
  58.                     // パラメータが不一致であればスキップ
  59.                     continue;
  60.                 }
  61.             }
  62.             $limiterId 'limiter.'.$id;
  63.             if (!$this->locator->has($limiterId)) {
  64.                 continue;
  65.             }
  66.             /** @var RateLimiterFactory $factory */
  67.             $factory $this->locator->get($limiterId);
  68.             if (in_array('customer'$config['type']) || in_array('user'$config['type'])) {
  69.                 $User $this->requestContext->getCurrentUser();
  70.                 if ($User instanceof UserInterface) {
  71.                     $limiter $factory->create($User->getId());
  72.                     if (!$limiter->consume()->isAccepted()) {
  73.                         throw new TooManyRequestsHttpException();
  74.                     }
  75.                 }
  76.             }
  77.             if (in_array('ip'$config['type'])) {
  78.                 $limiter $factory->create($request->getClientIp());
  79.                 if (!$limiter->consume()->isAccepted()) {
  80.                     throw new TooManyRequestsHttpException();
  81.                 }
  82.             }
  83.         }
  84.     }
  85.     /**
  86.      * {@inheritdoc}
  87.      */
  88.     public static function getSubscribedEvents()
  89.     {
  90.         return [
  91.             KernelEvents::CONTROLLER => ['onController'0],
  92.         ];
  93.     }
  94. }