reflector->hasAnnotation('BruteForceProtection')) { $action = $this->reflector->getAnnotationParameter('BruteForceProtection', 'action'); $this->delaySlept += $this->throttler->sleepDelayOrThrowOnMax($this->request->getRemoteAddress(), $action); } else { $reflectionMethod = new ReflectionMethod($controller, $methodName); $attributes = $reflectionMethod->getAttributes(BruteForceProtection::class); if (!empty($attributes)) { $remoteAddress = $this->request->getRemoteAddress(); foreach ($attributes as $attribute) { /** @var BruteForceProtection $protection */ $protection = $attribute->newInstance(); $action = $protection->getAction(); $this->delaySlept += $this->throttler->sleepDelayOrThrowOnMax($remoteAddress, $action); } } } } /** * {@inheritDoc} */ public function afterController($controller, $methodName, Response $response) { if ($response->isThrottled()) { try { if ($this->reflector->hasAnnotation('BruteForceProtection')) { $action = $this->reflector->getAnnotationParameter('BruteForceProtection', 'action'); $ip = $this->request->getRemoteAddress(); $this->throttler->registerAttempt($action, $ip, $response->getThrottleMetadata()); $this->delaySlept += $this->throttler->sleepDelayOrThrowOnMax($ip, $action); } else { $reflectionMethod = new ReflectionMethod($controller, $methodName); $attributes = $reflectionMethod->getAttributes(BruteForceProtection::class); if (!empty($attributes)) { $ip = $this->request->getRemoteAddress(); $metaData = $response->getThrottleMetadata(); foreach ($attributes as $attribute) { /** @var BruteForceProtection $protection */ $protection = $attribute->newInstance(); $action = $protection->getAction(); if (!isset($metaData['action']) || $metaData['action'] === $action) { $this->throttler->registerAttempt($action, $ip, $metaData); $this->delaySlept += $this->throttler->sleepDelayOrThrowOnMax($ip, $action); } } } else { $this->logger->debug('Response for ' . get_class($controller) . '::' . $methodName . ' got bruteforce throttled but has no annotation nor attribute defined.'); } } } catch (MaxDelayReached $e) { if ($controller instanceof OCSController) { throw new OCSException($e->getMessage(), Http::STATUS_TOO_MANY_REQUESTS); } return new TooManyRequestsResponse(); } } if ($this->delaySlept) { $response->addHeader('X-Nextcloud-Bruteforce-Throttled', $this->delaySlept . 'ms'); } return parent::afterController($controller, $methodName, $response); } /** * @param Controller $controller * @param string $methodName * @param \Exception $exception * @throws \Exception * @return Response */ public function afterException($controller, $methodName, \Exception $exception): Response { if ($exception instanceof MaxDelayReached) { if ($controller instanceof OCSController) { throw new OCSException($exception->getMessage(), Http::STATUS_TOO_MANY_REQUESTS); } return new TooManyRequestsResponse(); } throw $exception; } }