@@ -1,5 +1,5 @@ |
||
| 1 | 1 | <?php |
| 2 | -declare(strict_types=1); |
|
| 2 | +declare(strict_types = 1); |
|
| 3 | 3 | /** |
| 4 | 4 | * @copyright Copyright (c) 2017 Lukas Reschke <[email protected]> |
| 5 | 5 | * |
@@ -33,26 +33,26 @@ |
||
| 33 | 33 | * @package OC\Security\RateLimiting\Backend |
| 34 | 34 | */ |
| 35 | 35 | interface IBackend { |
| 36 | - /** |
|
| 37 | - * Gets the amount of attempts within the last specified seconds |
|
| 38 | - * |
|
| 39 | - * @param string $methodIdentifier Identifier for the method |
|
| 40 | - * @param string $userIdentifier Identifier for the user |
|
| 41 | - * @param int $seconds Seconds to look back at |
|
| 42 | - * @return int |
|
| 43 | - */ |
|
| 44 | - public function getAttempts(string $methodIdentifier, |
|
| 45 | - string $userIdentifier, |
|
| 46 | - int $seconds): int; |
|
| 36 | + /** |
|
| 37 | + * Gets the amount of attempts within the last specified seconds |
|
| 38 | + * |
|
| 39 | + * @param string $methodIdentifier Identifier for the method |
|
| 40 | + * @param string $userIdentifier Identifier for the user |
|
| 41 | + * @param int $seconds Seconds to look back at |
|
| 42 | + * @return int |
|
| 43 | + */ |
|
| 44 | + public function getAttempts(string $methodIdentifier, |
|
| 45 | + string $userIdentifier, |
|
| 46 | + int $seconds): int; |
|
| 47 | 47 | |
| 48 | - /** |
|
| 49 | - * Registers an attempt |
|
| 50 | - * |
|
| 51 | - * @param string $methodIdentifier Identifier for the method |
|
| 52 | - * @param string $userIdentifier Identifier for the user |
|
| 53 | - * @param int $period Period in seconds how long this attempt should be stored |
|
| 54 | - */ |
|
| 55 | - public function registerAttempt(string $methodIdentifier, |
|
| 56 | - string $userIdentifier, |
|
| 57 | - int $period); |
|
| 48 | + /** |
|
| 49 | + * Registers an attempt |
|
| 50 | + * |
|
| 51 | + * @param string $methodIdentifier Identifier for the method |
|
| 52 | + * @param string $userIdentifier Identifier for the user |
|
| 53 | + * @param int $period Period in seconds how long this attempt should be stored |
|
| 54 | + */ |
|
| 55 | + public function registerAttempt(string $methodIdentifier, |
|
| 56 | + string $userIdentifier, |
|
| 57 | + int $period); |
|
| 58 | 58 | } |
@@ -34,77 +34,77 @@ |
||
| 34 | 34 | use OCP\IUserSession; |
| 35 | 35 | |
| 36 | 36 | class Limiter { |
| 37 | - /** @var IBackend */ |
|
| 38 | - private $backend; |
|
| 39 | - /** @var ITimeFactory */ |
|
| 40 | - private $timeFactory; |
|
| 37 | + /** @var IBackend */ |
|
| 38 | + private $backend; |
|
| 39 | + /** @var ITimeFactory */ |
|
| 40 | + private $timeFactory; |
|
| 41 | 41 | |
| 42 | - /** |
|
| 43 | - * @param IUserSession $userSession |
|
| 44 | - * @param IRequest $request |
|
| 45 | - * @param ITimeFactory $timeFactory |
|
| 46 | - * @param IBackend $backend |
|
| 47 | - */ |
|
| 48 | - public function __construct(IUserSession $userSession, |
|
| 49 | - IRequest $request, |
|
| 50 | - ITimeFactory $timeFactory, |
|
| 51 | - IBackend $backend) { |
|
| 52 | - $this->backend = $backend; |
|
| 53 | - $this->timeFactory = $timeFactory; |
|
| 54 | - } |
|
| 42 | + /** |
|
| 43 | + * @param IUserSession $userSession |
|
| 44 | + * @param IRequest $request |
|
| 45 | + * @param ITimeFactory $timeFactory |
|
| 46 | + * @param IBackend $backend |
|
| 47 | + */ |
|
| 48 | + public function __construct(IUserSession $userSession, |
|
| 49 | + IRequest $request, |
|
| 50 | + ITimeFactory $timeFactory, |
|
| 51 | + IBackend $backend) { |
|
| 52 | + $this->backend = $backend; |
|
| 53 | + $this->timeFactory = $timeFactory; |
|
| 54 | + } |
|
| 55 | 55 | |
| 56 | - /** |
|
| 57 | - * @param string $methodIdentifier |
|
| 58 | - * @param string $userIdentifier |
|
| 59 | - * @param int $period |
|
| 60 | - * @param int $limit |
|
| 61 | - * @throws RateLimitExceededException |
|
| 62 | - */ |
|
| 63 | - private function register(string $methodIdentifier, |
|
| 64 | - string $userIdentifier, |
|
| 65 | - int $period, |
|
| 66 | - int $limit) { |
|
| 67 | - $existingAttempts = $this->backend->getAttempts($methodIdentifier, $userIdentifier, $period); |
|
| 68 | - if ($existingAttempts >= $limit) { |
|
| 69 | - throw new RateLimitExceededException(); |
|
| 70 | - } |
|
| 56 | + /** |
|
| 57 | + * @param string $methodIdentifier |
|
| 58 | + * @param string $userIdentifier |
|
| 59 | + * @param int $period |
|
| 60 | + * @param int $limit |
|
| 61 | + * @throws RateLimitExceededException |
|
| 62 | + */ |
|
| 63 | + private function register(string $methodIdentifier, |
|
| 64 | + string $userIdentifier, |
|
| 65 | + int $period, |
|
| 66 | + int $limit) { |
|
| 67 | + $existingAttempts = $this->backend->getAttempts($methodIdentifier, $userIdentifier, $period); |
|
| 68 | + if ($existingAttempts >= $limit) { |
|
| 69 | + throw new RateLimitExceededException(); |
|
| 70 | + } |
|
| 71 | 71 | |
| 72 | - $this->backend->registerAttempt($methodIdentifier, $userIdentifier, $this->timeFactory->getTime()); |
|
| 73 | - } |
|
| 72 | + $this->backend->registerAttempt($methodIdentifier, $userIdentifier, $this->timeFactory->getTime()); |
|
| 73 | + } |
|
| 74 | 74 | |
| 75 | - /** |
|
| 76 | - * Registers attempt for an anonymous request |
|
| 77 | - * |
|
| 78 | - * @param string $identifier |
|
| 79 | - * @param int $anonLimit |
|
| 80 | - * @param int $anonPeriod |
|
| 81 | - * @param string $ip |
|
| 82 | - * @throws RateLimitExceededException |
|
| 83 | - */ |
|
| 84 | - public function registerAnonRequest(string $identifier, |
|
| 85 | - int $anonLimit, |
|
| 86 | - int $anonPeriod, |
|
| 87 | - string $ip) { |
|
| 88 | - $ipSubnet = (new IpAddress($ip))->getSubnet(); |
|
| 75 | + /** |
|
| 76 | + * Registers attempt for an anonymous request |
|
| 77 | + * |
|
| 78 | + * @param string $identifier |
|
| 79 | + * @param int $anonLimit |
|
| 80 | + * @param int $anonPeriod |
|
| 81 | + * @param string $ip |
|
| 82 | + * @throws RateLimitExceededException |
|
| 83 | + */ |
|
| 84 | + public function registerAnonRequest(string $identifier, |
|
| 85 | + int $anonLimit, |
|
| 86 | + int $anonPeriod, |
|
| 87 | + string $ip) { |
|
| 88 | + $ipSubnet = (new IpAddress($ip))->getSubnet(); |
|
| 89 | 89 | |
| 90 | - $anonHashIdentifier = hash('sha512', 'anon::' . $identifier . $ipSubnet); |
|
| 91 | - $this->register($identifier, $anonHashIdentifier, $anonPeriod, $anonLimit); |
|
| 92 | - } |
|
| 90 | + $anonHashIdentifier = hash('sha512', 'anon::' . $identifier . $ipSubnet); |
|
| 91 | + $this->register($identifier, $anonHashIdentifier, $anonPeriod, $anonLimit); |
|
| 92 | + } |
|
| 93 | 93 | |
| 94 | - /** |
|
| 95 | - * Registers attempt for an authenticated request |
|
| 96 | - * |
|
| 97 | - * @param string $identifier |
|
| 98 | - * @param int $userLimit |
|
| 99 | - * @param int $userPeriod |
|
| 100 | - * @param IUser $user |
|
| 101 | - * @throws RateLimitExceededException |
|
| 102 | - */ |
|
| 103 | - public function registerUserRequest(string $identifier, |
|
| 104 | - int $userLimit, |
|
| 105 | - int $userPeriod, |
|
| 106 | - IUser $user) { |
|
| 107 | - $userHashIdentifier = hash('sha512', 'user::' . $identifier . $user->getUID()); |
|
| 108 | - $this->register($identifier, $userHashIdentifier, $userPeriod, $userLimit); |
|
| 109 | - } |
|
| 94 | + /** |
|
| 95 | + * Registers attempt for an authenticated request |
|
| 96 | + * |
|
| 97 | + * @param string $identifier |
|
| 98 | + * @param int $userLimit |
|
| 99 | + * @param int $userPeriod |
|
| 100 | + * @param IUser $user |
|
| 101 | + * @throws RateLimitExceededException |
|
| 102 | + */ |
|
| 103 | + public function registerUserRequest(string $identifier, |
|
| 104 | + int $userLimit, |
|
| 105 | + int $userPeriod, |
|
| 106 | + IUser $user) { |
|
| 107 | + $userHashIdentifier = hash('sha512', 'user::' . $identifier . $user->getUID()); |
|
| 108 | + $this->register($identifier, $userHashIdentifier, $userPeriod, $userLimit); |
|
| 109 | + } |
|
| 110 | 110 | } |
@@ -1,5 +1,5 @@ discard block |
||
| 1 | 1 | <?php |
| 2 | -declare(strict_types=1); |
|
| 2 | +declare(strict_types = 1); |
|
| 3 | 3 | /** |
| 4 | 4 | * @copyright Copyright (c) 2017 Lukas Reschke <[email protected]> |
| 5 | 5 | * |
@@ -86,7 +86,7 @@ discard block |
||
| 86 | 86 | string $ip) { |
| 87 | 87 | $ipSubnet = (new IpAddress($ip))->getSubnet(); |
| 88 | 88 | |
| 89 | - $anonHashIdentifier = hash('sha512', 'anon::' . $identifier . $ipSubnet); |
|
| 89 | + $anonHashIdentifier = hash('sha512', 'anon::'.$identifier.$ipSubnet); |
|
| 90 | 90 | $this->register($identifier, $anonHashIdentifier, $anonPeriod, $anonLimit); |
| 91 | 91 | } |
| 92 | 92 | |
@@ -103,7 +103,7 @@ discard block |
||
| 103 | 103 | int $userLimit, |
| 104 | 104 | int $userPeriod, |
| 105 | 105 | IUser $user) { |
| 106 | - $userHashIdentifier = hash('sha512', 'user::' . $identifier . $user->getUID()); |
|
| 106 | + $userHashIdentifier = hash('sha512', 'user::'.$identifier.$user->getUID()); |
|
| 107 | 107 | $this->register($identifier, $userHashIdentifier, $userPeriod, $userLimit); |
| 108 | 108 | } |
| 109 | 109 | } |
@@ -36,90 +36,90 @@ |
||
| 36 | 36 | * @package OC\Security\RateLimiting\Backend |
| 37 | 37 | */ |
| 38 | 38 | class MemoryCache implements IBackend { |
| 39 | - /** @var ICache */ |
|
| 40 | - private $cache; |
|
| 41 | - /** @var ITimeFactory */ |
|
| 42 | - private $timeFactory; |
|
| 39 | + /** @var ICache */ |
|
| 40 | + private $cache; |
|
| 41 | + /** @var ITimeFactory */ |
|
| 42 | + private $timeFactory; |
|
| 43 | 43 | |
| 44 | - /** |
|
| 45 | - * @param ICacheFactory $cacheFactory |
|
| 46 | - * @param ITimeFactory $timeFactory |
|
| 47 | - */ |
|
| 48 | - public function __construct(ICacheFactory $cacheFactory, |
|
| 49 | - ITimeFactory $timeFactory) { |
|
| 50 | - $this->cache = $cacheFactory->createDistributed(__CLASS__); |
|
| 51 | - $this->timeFactory = $timeFactory; |
|
| 52 | - } |
|
| 44 | + /** |
|
| 45 | + * @param ICacheFactory $cacheFactory |
|
| 46 | + * @param ITimeFactory $timeFactory |
|
| 47 | + */ |
|
| 48 | + public function __construct(ICacheFactory $cacheFactory, |
|
| 49 | + ITimeFactory $timeFactory) { |
|
| 50 | + $this->cache = $cacheFactory->createDistributed(__CLASS__); |
|
| 51 | + $this->timeFactory = $timeFactory; |
|
| 52 | + } |
|
| 53 | 53 | |
| 54 | - /** |
|
| 55 | - * @param string $methodIdentifier |
|
| 56 | - * @param string $userIdentifier |
|
| 57 | - * @return string |
|
| 58 | - */ |
|
| 59 | - private function hash(string $methodIdentifier, |
|
| 60 | - string $userIdentifier): string { |
|
| 61 | - return hash('sha512', $methodIdentifier . $userIdentifier); |
|
| 62 | - } |
|
| 54 | + /** |
|
| 55 | + * @param string $methodIdentifier |
|
| 56 | + * @param string $userIdentifier |
|
| 57 | + * @return string |
|
| 58 | + */ |
|
| 59 | + private function hash(string $methodIdentifier, |
|
| 60 | + string $userIdentifier): string { |
|
| 61 | + return hash('sha512', $methodIdentifier . $userIdentifier); |
|
| 62 | + } |
|
| 63 | 63 | |
| 64 | - /** |
|
| 65 | - * @param string $identifier |
|
| 66 | - * @return array |
|
| 67 | - */ |
|
| 68 | - private function getExistingAttempts(string $identifier): array { |
|
| 69 | - $cachedAttempts = $this->cache->get($identifier); |
|
| 70 | - if ($cachedAttempts === null) { |
|
| 71 | - return []; |
|
| 72 | - } |
|
| 64 | + /** |
|
| 65 | + * @param string $identifier |
|
| 66 | + * @return array |
|
| 67 | + */ |
|
| 68 | + private function getExistingAttempts(string $identifier): array { |
|
| 69 | + $cachedAttempts = $this->cache->get($identifier); |
|
| 70 | + if ($cachedAttempts === null) { |
|
| 71 | + return []; |
|
| 72 | + } |
|
| 73 | 73 | |
| 74 | - $cachedAttempts = json_decode($cachedAttempts, true); |
|
| 75 | - if(\is_array($cachedAttempts)) { |
|
| 76 | - return $cachedAttempts; |
|
| 77 | - } |
|
| 74 | + $cachedAttempts = json_decode($cachedAttempts, true); |
|
| 75 | + if(\is_array($cachedAttempts)) { |
|
| 76 | + return $cachedAttempts; |
|
| 77 | + } |
|
| 78 | 78 | |
| 79 | - return []; |
|
| 80 | - } |
|
| 79 | + return []; |
|
| 80 | + } |
|
| 81 | 81 | |
| 82 | - /** |
|
| 83 | - * {@inheritDoc} |
|
| 84 | - */ |
|
| 85 | - public function getAttempts(string $methodIdentifier, |
|
| 86 | - string $userIdentifier, |
|
| 87 | - int $seconds): int { |
|
| 88 | - $identifier = $this->hash($methodIdentifier, $userIdentifier); |
|
| 89 | - $existingAttempts = $this->getExistingAttempts($identifier); |
|
| 82 | + /** |
|
| 83 | + * {@inheritDoc} |
|
| 84 | + */ |
|
| 85 | + public function getAttempts(string $methodIdentifier, |
|
| 86 | + string $userIdentifier, |
|
| 87 | + int $seconds): int { |
|
| 88 | + $identifier = $this->hash($methodIdentifier, $userIdentifier); |
|
| 89 | + $existingAttempts = $this->getExistingAttempts($identifier); |
|
| 90 | 90 | |
| 91 | - $count = 0; |
|
| 92 | - $currentTime = $this->timeFactory->getTime(); |
|
| 93 | - /** @var array $existingAttempts */ |
|
| 94 | - foreach ($existingAttempts as $attempt) { |
|
| 95 | - if(($attempt + $seconds) > $currentTime) { |
|
| 96 | - $count++; |
|
| 97 | - } |
|
| 98 | - } |
|
| 91 | + $count = 0; |
|
| 92 | + $currentTime = $this->timeFactory->getTime(); |
|
| 93 | + /** @var array $existingAttempts */ |
|
| 94 | + foreach ($existingAttempts as $attempt) { |
|
| 95 | + if(($attempt + $seconds) > $currentTime) { |
|
| 96 | + $count++; |
|
| 97 | + } |
|
| 98 | + } |
|
| 99 | 99 | |
| 100 | - return $count; |
|
| 101 | - } |
|
| 100 | + return $count; |
|
| 101 | + } |
|
| 102 | 102 | |
| 103 | - /** |
|
| 104 | - * {@inheritDoc} |
|
| 105 | - */ |
|
| 106 | - public function registerAttempt(string $methodIdentifier, |
|
| 107 | - string $userIdentifier, |
|
| 108 | - int $period) { |
|
| 109 | - $identifier = $this->hash($methodIdentifier, $userIdentifier); |
|
| 110 | - $existingAttempts = $this->getExistingAttempts($identifier); |
|
| 111 | - $currentTime = $this->timeFactory->getTime(); |
|
| 103 | + /** |
|
| 104 | + * {@inheritDoc} |
|
| 105 | + */ |
|
| 106 | + public function registerAttempt(string $methodIdentifier, |
|
| 107 | + string $userIdentifier, |
|
| 108 | + int $period) { |
|
| 109 | + $identifier = $this->hash($methodIdentifier, $userIdentifier); |
|
| 110 | + $existingAttempts = $this->getExistingAttempts($identifier); |
|
| 111 | + $currentTime = $this->timeFactory->getTime(); |
|
| 112 | 112 | |
| 113 | - // Unset all attempts older than $period |
|
| 114 | - foreach ($existingAttempts as $key => $attempt) { |
|
| 115 | - if(($attempt + $period) < $currentTime) { |
|
| 116 | - unset($existingAttempts[$key]); |
|
| 117 | - } |
|
| 118 | - } |
|
| 119 | - $existingAttempts = array_values($existingAttempts); |
|
| 113 | + // Unset all attempts older than $period |
|
| 114 | + foreach ($existingAttempts as $key => $attempt) { |
|
| 115 | + if(($attempt + $period) < $currentTime) { |
|
| 116 | + unset($existingAttempts[$key]); |
|
| 117 | + } |
|
| 118 | + } |
|
| 119 | + $existingAttempts = array_values($existingAttempts); |
|
| 120 | 120 | |
| 121 | - // Store the new attempt |
|
| 122 | - $existingAttempts[] = (string)$currentTime; |
|
| 123 | - $this->cache->set($identifier, json_encode($existingAttempts)); |
|
| 124 | - } |
|
| 121 | + // Store the new attempt |
|
| 122 | + $existingAttempts[] = (string)$currentTime; |
|
| 123 | + $this->cache->set($identifier, json_encode($existingAttempts)); |
|
| 124 | + } |
|
| 125 | 125 | } |
@@ -1,5 +1,5 @@ discard block |
||
| 1 | 1 | <?php |
| 2 | -declare(strict_types=1); |
|
| 2 | +declare(strict_types = 1); |
|
| 3 | 3 | /** |
| 4 | 4 | * @copyright Copyright (c) 2017 Lukas Reschke <[email protected]> |
| 5 | 5 | * |
@@ -57,7 +57,7 @@ discard block |
||
| 57 | 57 | */ |
| 58 | 58 | private function hash(string $methodIdentifier, |
| 59 | 59 | string $userIdentifier): string { |
| 60 | - return hash('sha512', $methodIdentifier . $userIdentifier); |
|
| 60 | + return hash('sha512', $methodIdentifier.$userIdentifier); |
|
| 61 | 61 | } |
| 62 | 62 | |
| 63 | 63 | /** |
@@ -71,7 +71,7 @@ discard block |
||
| 71 | 71 | } |
| 72 | 72 | |
| 73 | 73 | $cachedAttempts = json_decode($cachedAttempts, true); |
| 74 | - if(\is_array($cachedAttempts)) { |
|
| 74 | + if (\is_array($cachedAttempts)) { |
|
| 75 | 75 | return $cachedAttempts; |
| 76 | 76 | } |
| 77 | 77 | |
@@ -91,7 +91,7 @@ discard block |
||
| 91 | 91 | $currentTime = $this->timeFactory->getTime(); |
| 92 | 92 | /** @var array $existingAttempts */ |
| 93 | 93 | foreach ($existingAttempts as $attempt) { |
| 94 | - if(($attempt + $seconds) > $currentTime) { |
|
| 94 | + if (($attempt + $seconds) > $currentTime) { |
|
| 95 | 95 | $count++; |
| 96 | 96 | } |
| 97 | 97 | } |
@@ -111,14 +111,14 @@ discard block |
||
| 111 | 111 | |
| 112 | 112 | // Unset all attempts older than $period |
| 113 | 113 | foreach ($existingAttempts as $key => $attempt) { |
| 114 | - if(($attempt + $period) < $currentTime) { |
|
| 114 | + if (($attempt + $period) < $currentTime) { |
|
| 115 | 115 | unset($existingAttempts[$key]); |
| 116 | 116 | } |
| 117 | 117 | } |
| 118 | 118 | $existingAttempts = array_values($existingAttempts); |
| 119 | 119 | |
| 120 | 120 | // Store the new attempt |
| 121 | - $existingAttempts[] = (string)$currentTime; |
|
| 121 | + $existingAttempts[] = (string) $currentTime; |
|
| 122 | 122 | $this->cache->set($identifier, json_encode($existingAttempts)); |
| 123 | 123 | } |
| 124 | 124 | } |
@@ -1,5 +1,5 @@ |
||
| 1 | 1 | <?php |
| 2 | -declare(strict_types=1); |
|
| 2 | +declare(strict_types = 1); |
|
| 3 | 3 | /** |
| 4 | 4 | * @copyright Copyright (c) 2017 Lukas Reschke <[email protected]> |
| 5 | 5 | * |