/home/suroeste/public_html/payments.transportessuroeste.com/src/Middleware
NameSizeModeActions
AuthMiddleware.php55210644editdlrm
RateLimiter.php67230644editdlrm
SecurityMiddleware.php97050644editdlrm
Edit: /home/suroeste/public_html/payments.transportessuroeste.com/src/Middleware/RateLimiter.php (6723B)
db = Database::getInstance(); $this->maxRequests = SECURITY_CONFIG['rate_limit_requests'] ?? 100; $this->windowSeconds = SECURITY_CONFIG['rate_limit_window'] ?? 60; $this->banTime = SECURITY_CONFIG['rate_limit_ban_time'] ?? 3600; } /** * Verificar y aplicar rate limiting */ public function check(string $identifier, string $endpoint = '/'): void { try { if ($this->isBlocked($identifier)) { LogService::security('rate_limit_exceeded', "IP bloqueada: {$identifier}", [ 'identifier' => $identifier, 'endpoint' => $endpoint ]); throw new RateLimitException('Demasiadas peticiones', $this->banTime); } $count = $this->incrementCounter($identifier, $endpoint); if ($count > $this->maxRequests) { $this->blockIdentifier($identifier); LogService::security('rate_limit_exceeded', "Limite excedido, bloqueando: {$identifier}", [ 'requests' => $count, 'limit' => $this->maxRequests ]); throw new RateLimitException('Limite de peticiones excedido', $this->banTime); } } catch (RateLimitException $e) { throw $e; } catch (\Exception $e) { LogService::error('rate_limiter', 'Error en rate limiter: ' . $e->getMessage()); } } /** * Verificar si IP esta bloqueada */ private function isBlocked(string $identifier): bool { try { $sql = "SELECT id FROM blocked_ips WHERE ip_address = ? AND (is_permanent = 1 OR expires_at > NOW())"; $stmt = $this->db->getConnection()->prepare($sql); $stmt->execute([$identifier]); return $stmt->fetch() !== false; } catch (\Exception $e) { return false; } } /** * Incrementar contador de peticiones */ private function incrementCounter(string $identifier, string $endpoint): int { $pdo = $this->db->getConnection(); $now = date('Y-m-d H:i:s'); $windowStart = date('Y-m-d H:i:s', time() - $this->windowSeconds); $windowEnd = date('Y-m-d H:i:s', time() + $this->windowSeconds); try { $stmt = $pdo->prepare("DELETE FROM rate_limit_tracking WHERE identifier = ? AND window_end < ?"); $stmt->execute([$identifier, $windowStart]); $stmt = $pdo->prepare( "SELECT id, request_count FROM rate_limit_tracking WHERE identifier = ? AND identifier_type = 'ip' AND endpoint = ? AND window_start <= ? AND window_end >= ?" ); $stmt->execute([$identifier, $endpoint, $now, $now]); $existing = $stmt->fetch(\PDO::FETCH_ASSOC); if ($existing) { $newCount = (int)$existing['request_count'] + 1; $stmt = $pdo->prepare("UPDATE rate_limit_tracking SET request_count = ? WHERE id = ?"); $stmt->execute([$newCount, $existing['id']]); return $newCount; } $stmt = $pdo->prepare( "INSERT INTO rate_limit_tracking (identifier, identifier_type, endpoint, request_count, window_start, window_end) VALUES (?, 'ip', ?, 1, ?, ?)" ); $stmt->execute([$identifier, $endpoint, $now, $windowEnd]); return 1; } catch (\Exception $e) { LogService::error('rate_limiter', 'Error MySQL incrementando contador: ' . $e->getMessage()); return 1; } } /** * Bloquear IP */ private function blockIdentifier(string $identifier): void { $pdo = $this->db->getConnection(); $expiresAt = date('Y-m-d H:i:s', time() + $this->banTime); try { $stmt = $pdo->prepare("SELECT id FROM blocked_ips WHERE ip_address = ?"); $stmt->execute([$identifier]); $existing = $stmt->fetch(); if ($existing) { $stmt = $pdo->prepare("UPDATE blocked_ips SET expires_at = ?, reason = 'Rate limit exceeded' WHERE ip_address = ?"); $stmt->execute([$expiresAt, $identifier]); } else { $stmt = $pdo->prepare( "INSERT INTO blocked_ips (ip_address, reason, blocked_by, is_permanent, expires_at) VALUES (?, 'Rate limit exceeded', 'system', 0, ?)" ); $stmt->execute([$identifier, $expiresAt]); } } catch (\Exception $e) { LogService::error('rate_limiter', 'Error bloqueando IP en MySQL: ' . $e->getMessage()); } } /** * Obtener headers de rate limit para respuesta */ public function getHeaders(string $identifier): array { try { $pdo = $this->db->getConnection(); $stmt = $pdo->prepare( "SELECT request_count, window_end FROM rate_limit_tracking WHERE identifier = ? ORDER BY window_end DESC LIMIT 1" ); $stmt->execute([$identifier]); $result = $stmt->fetch(\PDO::FETCH_ASSOC); $remaining = max(0, $this->maxRequests - ($result['request_count'] ?? 0)); $reset = $result ? strtotime($result['window_end']) : time() + $this->windowSeconds; return [ 'X-RateLimit-Limit' => $this->maxRequests, 'X-RateLimit-Remaining' => $remaining, 'X-RateLimit-Reset' => $reset ]; } catch (\Exception $e) { return [ 'X-RateLimit-Limit' => $this->maxRequests, 'X-RateLimit-Remaining' => $this->maxRequests, 'X-RateLimit-Reset' => time() + $this->windowSeconds ]; } } }