diff --git a/developer_manual/basics/controllers.rst b/developer_manual/basics/controllers.rst index fab06d621f3..cea041fb586 100644 --- a/developer_manual/basics/controllers.rst +++ b/developer_manual/basics/controllers.rst @@ -848,7 +848,7 @@ A controller method that turns off all checks would look like this: Rate limiting ------------- -Nextcloud supports rate limiting on a controller method basis. By default controller methods are not rate limited. Rate limiting should be used on expensive or security sensitive functions (e.g. password resets) to increase the overall security of your application. +Nextcloud supports rate limiting on a controller method basis and in a :ref:`programmatic way`. By default controller methods are not rate limited. Rate limiting should be used on expensive or security sensitive functions (e.g. password resets) to increase the overall security of your application. The native rate limiting will return a 429 status code to clients when the limit is reached and a default Nextcloud error page. When implementing rate limiting in your application, you should thus consider handling error situations where a 429 is returned by Nextcloud. diff --git a/developer_manual/digging_deeper/security.rst b/developer_manual/digging_deeper/security.rst index 7c78ce72bef..23ed46155dd 100644 --- a/developer_manual/digging_deeper/security.rst +++ b/developer_manual/digging_deeper/security.rst @@ -4,6 +4,59 @@ Security ======== +.. _programmatic-rate-limiting: + +Rate Limiting +------------- + +Rate limiting can be used to restrict how often someone can execute an operation in a defined time frame. For app framework controllers it is recommended to use rate limiting attributes. + +Outside controllers, e.g. in DAV code, it's also possible to guard operations by :ref:`injecting` ``\OCP\Security\RateLimiting\ILimiter`` and registering requests *before* the operation: + +.. code-block:: php + :emphasize-lines: 13-21, 27-36 + + limiter = $limiter; + } + + public function calledAnonymously(): void { + try { + $this->limiter->registerAnonRequest( + 'my-dav-plugin-anon', + 5, // Allow five executions … + 60 * 60, // … per hour + ); + } catch (IRateLimitExceededException $exception) { + // Respond with a HTTP 429 error + } + + // No rate limiting reached. Carry on. + } + + public function calledByUser(IUser $user): void { + try { + $this->limiter->registerUserRequest( + 'my-dav-plugin-user', + 5, // Allow five executions … + 60 * 60, // … per hour + $user + ); + } catch (IRateLimitExceededException $exception) { + // Respond with a HTTP 429 error + } + + // No rate limiting reached. Carry on. + } + } + Remote Host Validation ----------------------