如何在 Laravel Fortify 中对忘记密码请求进行速率限制?

J. *_*Doe 2 php laravel fortify

我正在使用 Fortify (Laravel 8),它确实为login和提供了 RateLimiter two-factor,但不为forgot-password请求提供。

如果没有(IP 地址)RateLimiter,一个非常简单的机器人就可以执行大量外发电子邮件,基本上会导致电子邮件服务暂停,或者在使用按发送电子邮件数量收费的 SMTP 服务时造成巨大成本。

我已经尝试过:

RateLimiter::for('forgot-password', function (Request $request) {
   return Limit::perMinute(1)->by($request->ip());
});
Run Code Online (Sandbox Code Playgroud)

在我的FortifyServiceProvider.php,但它不起作用!

文件中也没有routes/web.php手动应用节流中间件的路由。

小智 6

我也看过这个,后端实际上限制了对特定电子邮件的太多请求。但是,这是通过422 Unprocessable Entity(通常是验证错误)完成的,如下所示:

\n
{"message":"The given data was invalid.","errors":{"email":["Please wait before retrying."]}}\n
Run Code Online (Sandbox Code Playgroud)\n

我遇到你的问题是因为我希望基于IP 来限制/fortify/reset-password和(password.update/password.email) 。两者都需要用户的电子邮件地址,从而使攻击者能够测试现有的电子邮件地址,因为后端会很高兴地告诉您它是否存在\xe2\x80\x94,并且没有速率限制!上述现有速率限制 ( ) 仅针对一封特定电子邮件的多个请求才会生效。因此,如果有人要枚举可能的电子邮件,这将无济于事。/fortify/forgot-password422

\n

我的解决方案是reset-passwordand forgot-password(而是一种解决方法)。我将省略 ,reset-password因为它等于forgot-password

\n

但是,这需要您在web.php. 不会对任何供应商文件进行任何更改。您必须确保升级 fortify 后路由注册仍然等于原始路由(https://github.com/laravel/fortify/blob/master/routes/routes.php

\n
    \n
  1. 让我们添加一个新的速率限制器 [ app/Providers/FortifyServiceProvider.php]
  2. \n
\n

这将允许每个 IP 每分钟 10 个请求

\n
public function boot()\n    {\n        // ...\n        RateLimiter::for(\'forgot-password\', function (Request $request) {\n            return Limit::perMinute(10)->by($request->ip());\n        });\n    }\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 将其添加到您的强化配置中 [ config/fortify.php]
  2. \n
\n
 \'limiters\' => [\n        // ...\n        \'forgot-password\' => \'forgot-password\',\n    ],\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 确保您的强化服务提供商在您自己的路由服务提供商之前被调用(通过官方 Laravel 文档安装时就是这种情况)[ config/app.php]
  2. \n
\n
\'providers\' => [\n\n        // ...\n        /*\n         * Package Service Providers...\n         */\n        App\\Providers\\FortifyServiceProvider::class,\n\n\n        /*\n         * Application Service Providers...\n         */\n\n        // ...\n        App\\Providers\\RouteServiceProvider::class,\n\n    ],\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 您现在可以覆盖路由并附加速率限制器 [ routes/web.php]
  2. \n
\n
use Laravel\\Fortify\\Http\\Controllers\\PasswordResetLinkController;\n\n//...\n\n$limiter = config(\'fortify.limiters.forgot-password\');\n// Copied from\n// https://github.com/laravel/fortify/blob/c64f1e8263417179d06fd986ef8d716d4c5689e2/routes/routes.php#L55\n// with addition of the throttle middleware.\n// TODO: Keep this updated when updating fortify!\nRoute::post(config(\'fortify.prefix\', \'fortify\') . \'/forgot-password\', [PasswordResetLinkController::class, \'store\'])\n    ->middleware([\'guest\', \'throttle:\' . $limiter])\n    ->name(\'password.email\');\n
Run Code Online (Sandbox Code Playgroud)\n

来自一个 IP 的超过 10 个请求现在会429 Too Many Requests从您的后端向客户端抛出异常。

\n

这样做的好处是,您只覆盖路由注册,但仍然可以使用所有 fortify 功能,因为它使用库存控制器。

\n