46 lines
1.2 KiB
PHP
46 lines
1.2 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Http\Middleware;
|
||
|
|
|
||
|
|
use Closure;
|
||
|
|
use Illuminate\Cache\RateLimiter;
|
||
|
|
use Illuminate\Http\Request;
|
||
|
|
use Illuminate\Support\Facades\Log;
|
||
|
|
|
||
|
|
class ApiRateLimiter
|
||
|
|
{
|
||
|
|
protected $limiter;
|
||
|
|
|
||
|
|
public function __construct(RateLimiter $limiter)
|
||
|
|
{
|
||
|
|
$this->limiter = $limiter;
|
||
|
|
}
|
||
|
|
|
||
|
|
public function handle(Request $request, Closure $next)
|
||
|
|
{
|
||
|
|
$key = 'api-key-attempts:'.$request->ip();
|
||
|
|
|
||
|
|
// API Key가 없거나 유효하지 않은 경우 Rate Limiting 적용
|
||
|
|
if (! $request->header('X-API-KEY')) {
|
||
|
|
if ($this->limiter->tooManyAttempts($key, 10)) {
|
||
|
|
$seconds = $this->limiter->availableIn($key);
|
||
|
|
|
||
|
|
Log::warning('API Rate Limit Exceeded', [
|
||
|
|
'ip' => $request->ip(),
|
||
|
|
'uri' => $request->getRequestUri(),
|
||
|
|
'retry_after' => $seconds,
|
||
|
|
]);
|
||
|
|
|
||
|
|
return response()->json([
|
||
|
|
'message' => 'Too many attempts. Please try again later.',
|
||
|
|
'retry_after' => $seconds,
|
||
|
|
], 429);
|
||
|
|
}
|
||
|
|
|
||
|
|
$this->limiter->hit($key, 60); // 1분 동안 유지
|
||
|
|
}
|
||
|
|
|
||
|
|
return $next($request);
|
||
|
|
}
|
||
|
|
}
|