Laravel 接口限流实战:用 RateLimiter 防刷接口、按用户与 IP 定制配额

test12026-10-150 次阅读

为什么要限流

登录、发短信、搜索这类接口被人脚本刷起来,数据库和第三方服务先扛不住。Laravel 自带 RateLimiter,底层基于缓存(默认用 Redis),能在不写额外中间件代码的情况下按 key 限频。

在路由里直接用 throttle

// routes/api.php
use Illuminate\Support\Facades\Route;

Route::post('/login', [AuthController::class, 'login'])
    ->middleware('throttle:5,1'); // 每分钟最多 5 次

throttle:5,1 表示 1 分钟内最多 5 次,超出返回 429。响应头会带上 X-RateLimit-Limit 和 X-RateLimit-Remaining,前端能据此提示。

按用户区分限流 key

默认按 IP 限,但多人共享出口 IP 会误伤。用闭包自定义 key,让登录接口每人独立配额:

use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

RateLimiter::for('login', function (Request $request) {
    return Limit::perMinute(5)->by($request->user()?->id ?: $request->ip());
});

路由改用命名限制器:

Route::post('/login', ...)->middleware('throttle:login');

在代码里手动扣额度

有些逻辑不在路由层,比如发短信验证码,用 RateLimiter 门面手动判断:

use Illuminate\Support\Facades\RateLimiter;

$key = 'sms:' . $request->phone;
if (RateLimiter::tooManyAttempts($key, 1)) {
    $seconds = RateLimiter::availableIn($key);
    return response()->json(['msg' => "请 {$seconds} 秒后再试"], 429);
}
// 发送短信...
RateLimiter::hit($key, 60); // 60 秒窗口内计一次

生产建议

  • 限流 key 要带业务维度(用户 ID、手机号),否则共享 IP 会集体被拦。
  • 缓存必须可靠,用 Redis 而非数组或文件驱动,否则多实例下限流失效。
  • 给关键写接口都加限流,读接口可放宽,别一刀切把正常流量也挡了。
T

test1

文章作者

为什么要限流 登录、发短信、搜索这类接口被人脚本刷起来,数据库和第三方服务先扛不住。Laravel 自带 RateLi...

分类
技术
发布时间
2026-10-15
字数
约 1230 字
阅读
0 次