From 7f828fc1acc10d3c03930544607e933c51e47521 Mon Sep 17 00:00:00 2001 From: andrey-tm Date: Wed, 15 Nov 2017 21:08:01 +0200 Subject: [PATCH 01/12] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5fbbdae..bfe4a17 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "ethercreative/yii2-ip-ratelimiter", + "name": "andreyv/yii2-ip-ratelimiter", "description": "Allow guest clients to be rate limited, using their IP as the identifier.", "type": "yii2-module", "keywords": ["yii2", "ratelimiter"], From 8f299e9afa1f3a06d0878b84fae0c8cd5d975cad Mon Sep 17 00:00:00 2001 From: andreyv Date: Thu, 16 Nov 2017 00:20:10 +0200 Subject: [PATCH 02/12] Modified RateLimiter. Added actions check on which apply RateLimiter. --- .gitignore | 7 +-- IpRateLimiter.php | 61 ------------------- README.md | 10 +-- composer.json | 40 ++++++------ .../IpRateLimitInterface.php | 7 +-- src/IpRateLimiter.php | 58 ++++++++++++++++++ UserExample.php => src/UserIdentity.php | 9 +-- 7 files changed, 92 insertions(+), 100 deletions(-) delete mode 100644 IpRateLimiter.php rename IpRateLimitInterface.php => src/IpRateLimitInterface.php (75%) create mode 100644 src/IpRateLimiter.php rename UserExample.php => src/UserIdentity.php (88%) diff --git a/.gitignore b/.gitignore index c422267..49dbaea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ -composer.phar /vendor/ - -# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file -# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file -# composer.lock +/.idea/ +/composer.lock diff --git a/IpRateLimiter.php b/IpRateLimiter.php deleted file mode 100644 index ee1745b..0000000 --- a/IpRateLimiter.php +++ /dev/null @@ -1,61 +0,0 @@ -user; - - if ($this->separateRates) { - $user = $user ?: (Yii::$app->getUser() ? Yii::$app->getUser()->getIdentity(false) : null); - } - - /** @var IpRateLimitInterface $identityClass */ - $identityClass = Yii::$app->getUser()->identityClass; - - $user = $user ?: $identityClass::findByIp(Yii::$app->getRequest()->getUserIP(), $this->rateLimit, - $this->timePeriod); - - if ($user instanceof IpRateLimitInterface) { - Yii::trace('Check rate limit', __METHOD__); - - $this->checkRateLimit( - $user, - $this->request ?: Yii::$app->getRequest(), - $this->response ?: Yii::$app->getResponse(), - $action - ); - - return true; - } - - return parent::beforeAction($action); - } -} diff --git a/README.md b/README.md index 7481f77..f6b157d 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,13 @@ The preferred way to install this extension is through [composer](http://getcomp Either run ``` -php composer.phar require ethercreative/yii2-ip-ratelimiter "1.*" +php composer.phar require andreyv/yii2-ip-ratelimiter "1.*" ``` or add ``` -"ethercreative/yii2-ip-ratelimiter": "1.*" +"andreyv/yii2-ip-ratelimiter": "1.*" ``` to the require section of your `composer.json` file. @@ -31,7 +31,7 @@ public function behaviors() $behaviors = parent::behaviors(); $behaviors['rateLimiter'] = [ // Use class - 'class' => \ethercreative\ratelimiter\RateLimiter::className(), + 'class' => \andreyv\ratelimiter\RateLimiter::class, // The maximum number of allowed requests 'rateLimit' => 100, @@ -43,7 +43,7 @@ public function behaviors() // Defaults to true // - false: use one set of rates, whether you are authenticated or not // - true: use separate ratesfor guests and authenticated users - 'separateRates' => false, + 'separateRates' => true, // Whether to return HTTP headers containing the current rate limiting information 'enableRateLimitHeaders' => false, @@ -51,3 +51,5 @@ public function behaviors() return $behaviors; } ``` + +Forked from ethercreative/yii2-ip-ratelimiter. \ No newline at end of file diff --git a/composer.json b/composer.json index bfe4a17..e575994 100644 --- a/composer.json +++ b/composer.json @@ -1,23 +1,29 @@ { - "name": "andreyv/yii2-ip-ratelimiter", - "description": "Allow guest clients to be rate limited, using their IP as the identifier.", - "type": "yii2-module", - "keywords": ["yii2", "ratelimiter"], - "license": "MIT", - "authors": [ - { - "name": "Matt Edmonston", - "email": "matt@ethercreative.co.uk" - }, + "name": "andreyv/yii2-ip-ratelimiter", + "description": "Allow guest clients to be rate limited, using their IP as the identifier.", + "type": "yii2-module", + "keywords": ["yii2", "ratelimiter"], + "license": "MIT", + "authors": [ + { + "name": "Matt Edmonston", + "email": "matt@ethercreative.co.uk" + }, { "name": "Yaroslav Lukyanov", "email": "c_sharp@mail.ru" + }, + { + "name": "Andreyv V", + "email": "skifbrt@gmail.com" + } + ], + "require": { + "yiisoft/yii2": "*" + }, + "autoload": { + "psr-4": { + "andreyv\\ratelimiter\\": "src" } - ], - "require": {}, - "autoload": { - "psr-4": { - "ethercreative\\ratelimiter\\": "" - } - } + } } diff --git a/IpRateLimitInterface.php b/src/IpRateLimitInterface.php similarity index 75% rename from IpRateLimitInterface.php rename to src/IpRateLimitInterface.php index 225c379..9b5739f 100644 --- a/IpRateLimitInterface.php +++ b/src/IpRateLimitInterface.php @@ -1,14 +1,9 @@ actions) && (empty($this->actions) || in_array($action->id, $this->actions))) { + if ($this->separateRates && !$this->user) { + $this->user = Yii::$app->getUser() ? Yii::$app->getUser()->getIdentity(false) : null; + } + + if (!$this->user) { + /** @var IpRateLimitInterface $identityClass */ + $identityClass = Yii::$app->getUser()->identityClass; + if (!in_array(UserIdentity::class, class_implements($identityClass))) { + $identityClass = UserIdentity::class; + } + + $this->user = $identityClass::findByIp( + $this->request->getUserIP(), + $this->rateLimit, + $this->timePeriod + ); + } + + return parent::beforeAction($action); + } + return true; + } +} diff --git a/UserExample.php b/src/UserIdentity.php similarity index 88% rename from UserExample.php rename to src/UserIdentity.php index 3e6a7d4..91d6260 100644 --- a/UserExample.php +++ b/src/UserIdentity.php @@ -1,15 +1,10 @@ Date: Thu, 16 Nov 2017 00:33:16 +0200 Subject: [PATCH 03/12] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f6b157d..e0908a3 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,13 @@ The preferred way to install this extension is through [composer](http://getcomp Either run ``` -php composer.phar require andreyv/yii2-ip-ratelimiter "1.*" +php composer.phar require andreyv/yii2-ip-ratelimiter "2.*" ``` or add ``` -"andreyv/yii2-ip-ratelimiter": "1.*" +"andreyv/yii2-ip-ratelimiter": "2.*" ``` to the require section of your `composer.json` file. @@ -52,4 +52,4 @@ public function behaviors() } ``` -Forked from ethercreative/yii2-ip-ratelimiter. \ No newline at end of file +Forked from ethercreative/yii2-ip-ratelimiter. From 2cc76affd7d18a2e9ac517866d936a050fec4a01 Mon Sep 17 00:00:00 2001 From: andrey-tm Date: Wed, 22 Nov 2017 18:36:05 +0200 Subject: [PATCH 04/12] Renamed findByIp method to create, updated readme. --- README.md | 45 +++++++++++++++++++----------------- src/IpRateLimitInterface.php | 2 +- src/IpRateLimiter.php | 2 +- src/UserIdentity.php | 2 +- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index e0908a3..777e29e 100644 --- a/README.md +++ b/README.md @@ -28,27 +28,30 @@ Modify the bahavior method of the controller you want to rate limit ``` public function behaviors() { - $behaviors = parent::behaviors(); - $behaviors['rateLimiter'] = [ - // Use class - 'class' => \andreyv\ratelimiter\RateLimiter::class, - - // The maximum number of allowed requests - 'rateLimit' => 100, - - // The time period for the rates to apply to - 'timePeriod' => 600, - - // Separate rate limiting for guests and authenticated users - // Defaults to true - // - false: use one set of rates, whether you are authenticated or not - // - true: use separate ratesfor guests and authenticated users - 'separateRates' => true, - - // Whether to return HTTP headers containing the current rate limiting information - 'enableRateLimitHeaders' => false, - ]; - return $behaviors; + $behaviors = parent::behaviors(); + $behaviors['rateLimiter'] = [ + // Use class + 'class' => \andreyv\ratelimiter\RateLimiter::class, + + // The maximum number of allowed requests + 'rateLimit' => 100, + + // The time period for the rates to apply to + 'timePeriod' => 600, + + // Separate rate limiting for guests and authenticated users + // Defaults to false + // - false: use one set of rates, whether you are authenticated or not + // - true: use separate ratesfor guests and authenticated users + 'separateRates' => true, + + // Whether to return HTTP headers containing the current rate limiting information + 'enableRateLimitHeaders' => false, + + // Array of actions on which to apply ratelimiter, if empty - applies to all actions + 'actions' => ['index'], + ]; + return $behaviors; } ``` diff --git a/src/IpRateLimitInterface.php b/src/IpRateLimitInterface.php index 9b5739f..7f6e3b5 100644 --- a/src/IpRateLimitInterface.php +++ b/src/IpRateLimitInterface.php @@ -15,5 +15,5 @@ interface IpRateLimitInterface extends RateLimitInterface * * @return static */ - public static function findByIp($ip, $rateLimit, $timePeriod); + public static function create($ip, $rateLimit, $timePeriod); } \ No newline at end of file diff --git a/src/IpRateLimiter.php b/src/IpRateLimiter.php index faf1ac7..53c1211 100644 --- a/src/IpRateLimiter.php +++ b/src/IpRateLimiter.php @@ -44,7 +44,7 @@ public function beforeAction($action) $identityClass = UserIdentity::class; } - $this->user = $identityClass::findByIp( + $this->user = $identityClass::create( $this->request->getUserIP(), $this->rateLimit, $this->timePeriod diff --git a/src/UserIdentity.php b/src/UserIdentity.php index 91d6260..461f843 100644 --- a/src/UserIdentity.php +++ b/src/UserIdentity.php @@ -24,7 +24,7 @@ class UserIdentity implements IpRateLimitInterface /** * @inheritdoc */ - public static function findByIp($ip, $rateLimit, $timePeriod) + public static function create($ip, $rateLimit, $timePeriod) { $user = new static(); From 051457c3733aab10508436f07ed3a885e5b663d7 Mon Sep 17 00:00:00 2001 From: andrey-tm Date: Wed, 22 Nov 2017 19:40:23 +0200 Subject: [PATCH 05/12] Added testMode flag. --- README.md | 5 ++++- src/IpRateLimiter.php | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 777e29e..f30dca7 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ public function behaviors() $behaviors = parent::behaviors(); $behaviors['rateLimiter'] = [ // Use class - 'class' => \andreyv\ratelimiter\RateLimiter::class, + 'class' => \andreyv\ratelimiter\IpRateLimiter::class, // The maximum number of allowed requests 'rateLimit' => 100, @@ -50,6 +50,9 @@ public function behaviors() // Array of actions on which to apply ratelimiter, if empty - applies to all actions 'actions' => ['index'], + + // Allows to skip rate limiting for test environment + 'testMode' => true, ]; return $behaviors; } diff --git a/src/IpRateLimiter.php b/src/IpRateLimiter.php index 53c1211..6f227af 100644 --- a/src/IpRateLimiter.php +++ b/src/IpRateLimiter.php @@ -27,11 +27,20 @@ class IpRateLimiter extends RateLimiter */ public $actions = []; + /** + * @var bool allows to skip rate limiting for test environment + */ + public $testMode = false; + /** * @inheritdoc */ public function beforeAction($action) { + if ($this->testMode) { + return true; + } + if (is_array($this->actions) && (empty($this->actions) || in_array($action->id, $this->actions))) { if ($this->separateRates && !$this->user) { $this->user = Yii::$app->getUser() ? Yii::$app->getUser()->getIdentity(false) : null; From c67b1ec7bf8548ba3092607bf5b13805952c419d Mon Sep 17 00:00:00 2001 From: Pavel Terletskiy Date: Thu, 18 Oct 2018 17:32:25 +0300 Subject: [PATCH 06/12] Update IpRateLimiter.php When used trusted proxy, we need use limit by combination ip proxy server and X-Forwarded-For header. --- src/IpRateLimiter.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/IpRateLimiter.php b/src/IpRateLimiter.php index 6f227af..d18d560 100644 --- a/src/IpRateLimiter.php +++ b/src/IpRateLimiter.php @@ -54,7 +54,7 @@ public function beforeAction($action) } $this->user = $identityClass::create( - $this->request->getUserIP(), + $this->prepareIpListString(), $this->rateLimit, $this->timePeriod ); @@ -65,3 +65,14 @@ public function beforeAction($action) return true; } } +/* +When used trusted proxy, we need use limit by combination ip proxy server and X-Forwarded-For header. +*/ +protected function prepareIpListString() +{ + $ipList = [$this->request->getRemoteIP()]; + if ($this->request->headers->has('X-Forwarded-For')) { + $ipList[] = $this->request->headers->get('X-Forwarded-For'); + } + return implode(', ', $ipList); +} From 6fad69d8c94d387ebd0a3155ed0c5a1aeca9d2a6 Mon Sep 17 00:00:00 2001 From: Pavel Terletskiy Date: Thu, 18 Oct 2018 18:18:56 +0300 Subject: [PATCH 07/12] Update IpRateLimiter.php --- src/IpRateLimiter.php | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/IpRateLimiter.php b/src/IpRateLimiter.php index d18d560..41170e9 100644 --- a/src/IpRateLimiter.php +++ b/src/IpRateLimiter.php @@ -32,6 +32,11 @@ class IpRateLimiter extends RateLimiter */ public $testMode = false; + /** + * @var string tag in headers containing IP list + */ + public $ipHeader = 'X-Forwarded-For'; + /** * @inheritdoc */ @@ -64,15 +69,16 @@ public function beforeAction($action) } return true; } -} -/* -When used trusted proxy, we need use limit by combination ip proxy server and X-Forwarded-For header. -*/ -protected function prepareIpListString() -{ - $ipList = [$this->request->getRemoteIP()]; - if ($this->request->headers->has('X-Forwarded-For')) { - $ipList[] = $this->request->headers->get('X-Forwarded-For'); + + /* + When used trusted proxy, we need use limit by combination ip proxy server and X-Forwarded-For header. + */ + protected function prepareIpListString() + { + $ipList = [$this->request->getRemoteIP()]; + if ($this->request->headers->has($this->ipHeader)) { + $ipList[] = $this->request->headers->get($this->ipHeader); + } + return implode(', ', $ipList); } - return implode(', ', $ipList); } From 78b29c391f82c7449da4b2c7b25936baa912a7c0 Mon Sep 17 00:00:00 2001 From: Pavel Terletskiy Date: Thu, 18 Oct 2018 18:29:08 +0300 Subject: [PATCH 08/12] Update IpRateLimiter.php --- src/IpRateLimiter.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/IpRateLimiter.php b/src/IpRateLimiter.php index 41170e9..d927d5b 100644 --- a/src/IpRateLimiter.php +++ b/src/IpRateLimiter.php @@ -32,6 +32,11 @@ class IpRateLimiter extends RateLimiter */ public $testMode = false; + /** + * @var bool defines whether proxy enabled + */ + public $proxyEnabled = false; + /** * @var string tag in headers containing IP list */ @@ -76,9 +81,10 @@ public function beforeAction($action) protected function prepareIpListString() { $ipList = [$this->request->getRemoteIP()]; - if ($this->request->headers->has($this->ipHeader)) { + if ($this->proxyEnabled && $this->request->headers->has($this->ipHeader)) { $ipList[] = $this->request->headers->get($this->ipHeader); } + var_dump($ipList); return implode(', ', $ipList); } } From 51456e0e0826c9ad779e3fd64420da980b947786 Mon Sep 17 00:00:00 2001 From: Pavel Terletskiy Date: Thu, 18 Oct 2018 18:29:33 +0300 Subject: [PATCH 09/12] Update IpRateLimiter.php --- src/IpRateLimiter.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/IpRateLimiter.php b/src/IpRateLimiter.php index d927d5b..87e0f9c 100644 --- a/src/IpRateLimiter.php +++ b/src/IpRateLimiter.php @@ -84,7 +84,6 @@ protected function prepareIpListString() if ($this->proxyEnabled && $this->request->headers->has($this->ipHeader)) { $ipList[] = $this->request->headers->get($this->ipHeader); } - var_dump($ipList); return implode(', ', $ipList); } } From 848759d19fa9852b6a0c80eb7c5f0dbfcb5e74b2 Mon Sep 17 00:00:00 2001 From: Pavel Terletskiy Date: Thu, 18 Oct 2018 18:31:24 +0300 Subject: [PATCH 10/12] Update IpRateLimiter.php --- src/IpRateLimiter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/IpRateLimiter.php b/src/IpRateLimiter.php index 87e0f9c..3925949 100644 --- a/src/IpRateLimiter.php +++ b/src/IpRateLimiter.php @@ -40,7 +40,7 @@ class IpRateLimiter extends RateLimiter /** * @var string tag in headers containing IP list */ - public $ipHeader = 'X-Forwarded-For'; + public $proxyIpHeader = 'X-Forwarded-For'; /** * @inheritdoc @@ -81,8 +81,8 @@ public function beforeAction($action) protected function prepareIpListString() { $ipList = [$this->request->getRemoteIP()]; - if ($this->proxyEnabled && $this->request->headers->has($this->ipHeader)) { - $ipList[] = $this->request->headers->get($this->ipHeader); + if ($this->proxyEnabled && $this->request->headers->has($this->proxyIpHeader)) { + $ipList[] = $this->request->headers->get($this->proxyIpHeader); } return implode(', ', $ipList); } From b3401f686d5a7dc44c355e2573d7603821808573 Mon Sep 17 00:00:00 2001 From: utrain Date: Wed, 18 Jan 2023 13:52:00 +0200 Subject: [PATCH 11/12] fix getting real user IP with proxy --- README.md | 2 ++ src/IpRateLimiter.php | 9 ++------- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index f30dca7..91ee36a 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,8 @@ public function behaviors() // Allows to skip rate limiting for test environment 'testMode' => true, + // Defines whether proxy enabled, list of headers getting from request ipHeaders. By default ['X-Forwarded-For'] + 'proxyEnabled' => false ]; return $behaviors; } diff --git a/src/IpRateLimiter.php b/src/IpRateLimiter.php index 3925949..c59be4a 100644 --- a/src/IpRateLimiter.php +++ b/src/IpRateLimiter.php @@ -37,11 +37,6 @@ class IpRateLimiter extends RateLimiter */ public $proxyEnabled = false; - /** - * @var string tag in headers containing IP list - */ - public $proxyIpHeader = 'X-Forwarded-For'; - /** * @inheritdoc */ @@ -81,8 +76,8 @@ public function beforeAction($action) protected function prepareIpListString() { $ipList = [$this->request->getRemoteIP()]; - if ($this->proxyEnabled && $this->request->headers->has($this->proxyIpHeader)) { - $ipList[] = $this->request->headers->get($this->proxyIpHeader); + if ($this->proxyEnabled) { + $ipList[] = $this->request->getUserIP(); } return implode(', ', $ipList); } From af6386ffd9812d4375e9bc61f56e41c210d69ee3 Mon Sep 17 00:00:00 2001 From: ch Date: Wed, 18 Jan 2023 14:14:06 +0200 Subject: [PATCH 12/12] fixed getting real user IP. --- src/IpRateLimiter.php | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/IpRateLimiter.php b/src/IpRateLimiter.php index c59be4a..fac535d 100644 --- a/src/IpRateLimiter.php +++ b/src/IpRateLimiter.php @@ -59,7 +59,7 @@ public function beforeAction($action) } $this->user = $identityClass::create( - $this->prepareIpListString(), + $this->request->getUserIP(), $this->rateLimit, $this->timePeriod ); @@ -69,16 +69,4 @@ public function beforeAction($action) } return true; } - - /* - When used trusted proxy, we need use limit by combination ip proxy server and X-Forwarded-For header. - */ - protected function prepareIpListString() - { - $ipList = [$this->request->getRemoteIP()]; - if ($this->proxyEnabled) { - $ipList[] = $this->request->getUserIP(); - } - return implode(', ', $ipList); - } }