根据官方限流器改了下,针对不同的控制器和用户进行限流,大家帮忙看下这样有问题吗?
中间件代码
public function process(Request $request, callable $handler): Response
{
$response = $handler($request);
$user = Auth::guard('openapi_user')->user(true);
$controllerFull = $request->controller;
$controller = basename(str_replace('\\', '/', $controllerFull));
$route = $controller . '@' . $request->action;
// 定义需要特殊限流规则的路由
$route_array = ['LoginController@test'];
// 从配置读取默认限流参数
$defaultLimit = (int) config('app.ratelimit.limit'); // 默认限制次数
$ttl = (int) config('app.ratelimit.ttl'); // 限流时间窗口(秒)
// 判断当前路由是否属于特殊限流规则
if (in_array($route, $route_array)) {
// 查询用户在数据库中的个性化限流配置
$userRow = Db::table('iot_users')
->where('id', $user->id)
->first();
// 如果用户有自定义限制则使用,否则使用默认限制
$limit = $userRow ? (int) $userRow->limit : $defaultLimit;
// 限流 key:特殊接口 + 用户 ID
$key = "{$route}:{$user->id}";
} else {
// 非特殊接口统一限制,例如所有非特殊接口加起来最多 100 次
$limit = 100;
$key = "non_special:{$user->id}";
}
try {
// 检查限流(如果超出限制会抛出异常)
Limiter::check($key, $limit, $ttl, '请求过于频繁,请稍后再试');
} catch (RateLimitException $e) {
// 返回 429 Too Many Requests 状态码
return response($e->getMessage(), 429);
}
return $response;
}
2个回答
用万总的插件即可,很稳定,效率很高
他的不支持不同的用户和不同的控制吧?
这种只能自己添加中间件搞比较好 要不然谁知道你的用户id怎么拿到的 有session 有jwt的各种
所以我自己写了一个中间件,你也没看青我问啥。
// 查询用户在数据库中的个性化限流配置
这个地方搞一层缓存吧, 这样就算呗请求了也不会直接打到你的DB
是的,我得加一层缓存,谢谢