Limiter.php 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OC\Security\RateLimiting;
  8. use OC\Security\Normalizer\IpAddress;
  9. use OC\Security\RateLimiting\Backend\IBackend;
  10. use OC\Security\RateLimiting\Exception\RateLimitExceededException;
  11. use OCP\IUser;
  12. use OCP\Security\RateLimiting\ILimiter;
  13. class Limiter implements ILimiter {
  14. public function __construct(
  15. private IBackend $backend,
  16. ) {
  17. }
  18. /**
  19. * @param int $period in seconds
  20. * @throws RateLimitExceededException
  21. */
  22. private function register(
  23. string $methodIdentifier,
  24. string $userIdentifier,
  25. int $period,
  26. int $limit,
  27. ): void {
  28. $existingAttempts = $this->backend->getAttempts($methodIdentifier, $userIdentifier);
  29. if ($existingAttempts >= $limit) {
  30. throw new RateLimitExceededException();
  31. }
  32. $this->backend->registerAttempt($methodIdentifier, $userIdentifier, $period);
  33. }
  34. /**
  35. * Registers attempt for an anonymous request
  36. *
  37. * @param int $anonPeriod in seconds
  38. * @throws RateLimitExceededException
  39. */
  40. public function registerAnonRequest(
  41. string $identifier,
  42. int $anonLimit,
  43. int $anonPeriod,
  44. string $ip,
  45. ): void {
  46. $ipSubnet = (new IpAddress($ip))->getSubnet();
  47. $anonHashIdentifier = hash('sha512', 'anon::' . $identifier . $ipSubnet);
  48. $this->register($identifier, $anonHashIdentifier, $anonPeriod, $anonLimit);
  49. }
  50. /**
  51. * Registers attempt for an authenticated request
  52. *
  53. * @param int $userPeriod in seconds
  54. * @throws RateLimitExceededException
  55. */
  56. public function registerUserRequest(
  57. string $identifier,
  58. int $userLimit,
  59. int $userPeriod,
  60. IUser $user,
  61. ): void {
  62. $userHashIdentifier = hash('sha512', 'user::' . $identifier . $user->getUID());
  63. $this->register($identifier, $userHashIdentifier, $userPeriod, $userLimit);
  64. }
  65. }