Источник запроса в PHP: откуда пришел пользователь и какие параметры переданы

Раздел: HTTP и веб -> Обработка запросов

Основные подходы к получению источника запроса

В PHP информация о входящем HTTP-запросе доступна через суперглобальный массив $_SERVER. Этот массив содержит данные о сервере и окружении, включая IP-адрес клиента, адрес предыдущей страницы (Referer), строку запроса (Query String), HTTP-метод и многое другое. Правильное использование этих данных позволяет определить, откуда пришёл запрос, какие параметры были переданы и как обработать их безопасно.

Наиболее универсальное решение - обращаться к ключам массива $_SERVER с проверкой их существования. Основные ключи для определения источника запроса:

  • HTTP_REFERER - URL страницы, с которой был сделан запрос (если передан браузером).
  • REMOTE_ADDR - IP-адрес клиента (прямой).
  • HTTP_USER_AGENT - строка пользовательского агента (браузер, бот и т.д.).
  • QUERY_STRING - строка запроса после знака ?.
  • REQUEST_URI - полный URI запроса (путь и параметры).
  • REQUEST_METHOD - HTTP-метод (GET, POST, HEAD и т.д.).

Пример получения основных данных:


<?php
$referer = $_SERVER['HTTP_REFERER'] ?? 'не указан';
$ip = $_SERVER['REMOTE_ADDR'] ?? 'неизвестен';
$query = $_SERVER['QUERY_STRING'] ?? '';
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
echo "Referer: $referer\n";
echo "IP клиента: $ip\n";
echo "Строка запроса: $query\n";
echo "HTTP метод: $method\n";
?>
  

пример формы php (примеры html-форм с php)

Данный код безопасен благодаря оператору ?? (null coalescing), который присваивает значение по умолчанию в случае отсутствия ключа.

Как определить, с какого URL был отправлен запрос?

Использование ключа HTTP_REFERER - стандартный способ, но он не всегда надёжен: браузер может не отправлять заголовок Referer (например, при прямом вводе URL или из-за политик приватности). Чтобы избежать ошибок, нужно фильтровать полученное значение.


<?php
$referer = $_SERVER['HTTP_REFERER'] ?? null;
if ($referer) {
    // Валидация URL
    $safeReferer = filter_var($referer, FILTER_VALIDATE_URL);
    if ($safeReferer === false) {
        $safeReferer = 'Некорректный URL';
    }
    echo "Пришёл с: " . htmlspecialchars($safeReferer, ENT_QUOTES, 'UTF-8');
} else {
    echo "Referer отсутствует";
}
?>
  

Request admin php (обработка запроса в админке php)

Проблема: Referer может быть подделан или пуст. Не стоит полагаться на него для критичных проверок (например, для авторизации).

Решение: Использовать только для аналитики или необязательных действий, сочетать с другими данными (например, токеном сессии).

Как узнать IP-адрес посетителя?

Прямой IP клиента находится в REMOTE_ADDR. Однако если запрос проходит через прокси (CDN, балансировщик), реальный IP может быть в заголовках X-Forwarded-For или X-Real-IP. Пример безопасного извлечения с учётом доверенных прокси:


<?php
$ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
// Если используется доверенный прокси (например, Cloudflare), можно проверить заголовки
$trustedProxies = ['192.0.2.1', '10.0.0.1']; // пример
if (in_array($ip, $trustedProxies) && !empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $forwardedIps = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    $ip = trim(end($forwardedIps)); // последний IP в цепочке
}
echo "IP клиента: " . htmlspecialchars($ip, ENT_QUOTES, 'UTF-8');
?>
  

Source query php (источник запроса в php)

Проблема: Заголовки X-Forwarded-For легко подделываются, если не настроен доверенный прокси.

Решение: Никогда не доверять X-Forwarded-For без явного списка разрешённых прокси-серверов.

Как получить исходные GET-параметры?

Строка запроса хранится в $_SERVER['QUERY_STRING']. Однако для удобного доступа к отдельным параметрам лучше использовать суперглобальный массив $_GET, который автоматически разбирает строку запроса. Но если нужно получить именно сырую строку (например, для логирования), используйте QUERY_STRING.


<?php
$rawQuery = $_SERVER['QUERY_STRING'] ?? '';
if ($rawQuery) {
    parse_str($rawQuery, $params);
    echo "Параметры: ";
    print_r($params);
} else {
    echo "Запрос без параметров";
}
?>
  

Php post файл (обработка post-запросов с файлами в php)

Проблема: Строка запроса может содержать URL-кодированные символы. Без декодирования они некорректно отображаются.

Решение: Использовать urldecode() или полагаться на $_GET (PHP автоматически декодирует).

Как понять, какой HTTP метод использован?

Ключ REQUEST_METHOD содержит строку метода (GET, POST, PUT, DELETE и т.д.). Это необходимо для построения REST-подобных обработчиков.


<?php
$method = strtoupper($_SERVER['REQUEST_METHOD']);
switch ($method) {
    case 'GET':
        echo "Получен GET-запрос";
        break;
    case 'POST':
        echo "Получен POST-запрос";
        break;
    case 'DELETE':
        echo "Получен DELETE-запрос";
        break;
    default:
        echo "Метод $method не поддерживается";
        break;
}
?>
  

Php input action (ввод данных в php)

Проблема: Некоторые серверы могут не передавать все методы, либо клиент присылает невалидный метод.

Решение: Всегда проверять метод через белый список разрешённых.

Как восстановить полный URL текущей страницы?

Комбинация ключей HTTPS, HTTP_HOST, REQUEST_URI позволяет собрать абсолютный URL:


<?php
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'localhost';
$uri = $_SERVER['REQUEST_URI'] ?? '/';
$fullUrl = $scheme . '://' . $host . $uri;
echo "Полный URL: " . htmlspecialchars($fullUrl, ENT_QUOTES, 'UTF-8');
?>
  

Проблема: Возможны нестандартные порты (например, 8080), которые не отображаются в HTTP_HOST (если они не дефолтные).

Решение: Дополнительно проверять $_SERVER['SERVER_PORT'] и добавлять его при необходимости.

- Action php id (действие с параметром id в php)
- Actions php (действия (actions) в php)

Расширенные примеры работы с источником запроса

1. Разбор Referer с учётом подстроки и параметров

Часто требуется извлечь только домен из Referer или проверить, принадлежит ли он определённому сайту. Пример с разбором компонентов URL:

Пример

<?php
$referer = $_SERVER['HTTP_REFERER'] ?? 'https://example.com/page?ref=123';
$parts = parse_url($referer);
if ($parts) {
    echo "Схема: " . ($parts['scheme'] ?? 'нет') . "\n";
    echo "Хост: " . ($parts['host'] ?? 'нет') . "\n";
    echo "Путь: " . ($parts['path'] ?? 'нет') . "\n";
    echo "Строка запроса: " . ($parts['query'] ?? 'нет') . "\n";
    // Проверка на принадлежность домену
    $allowedDomain = 'mysite.com';
    if (isset($parts['host']) && $parts['host'] === $allowedDomain) {
        echo "Referer с доверенного домена";
    }
} else {
    echo "Невозможно разобрать Referer";
}
?>
Схема: https
Хост: example.com
Путь: /page
Строка запроса: ref=123
Referer с доверенного домена: нет (если example.com не совпадает)

2. Определение IP с поддержкой нескольких прокси и безопасность

Реализация функции, которая извлекает IP, проверяя заголовки от известных CDN (Cloudflare, AWS) и при этом отбрасывает подозрительные значения:

Пример

<?php
function getClientIp(): string {
    $trustedProxies = [
        '173.245.48.0/20', // Cloudflare (пример)
    ];
    $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
    // Простейшая проверка принадлежности к доверенной подсети (CIDR)
    foreach ($trustedProxies as $cidr) {
        if (ipInCidr($ip, $cidr)) {
            // Получаем IP из X-Forwarded-For
            if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                $ip = trim(end($ips));
            }
            break;
        }
    }
    return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : '0.0.0.0';
}

// Вспомогательная функция для проверки CIDR (упрощённая)
function ipInCidr(string $ip, string $cidr): bool {
    // ... реализация (опущена для краткости)
    return true; // заглушка
}

echo "Определённый IP: " . getClientIp();
?>
Определённый IP: 198.51.100.42 (пример)

3. Извлечение всех заголовков запроса с помощью getallheaders()

Функция getallheaders() возвращает ассоциативный массив всех HTTP-заголовков. Это удобно для отладки или если нужно обработать нестандартные заголовки (X-Custom). Пример:

Пример

<?php
$headers = getallheaders();
echo "<pre>";
print_r($headers);
echo "</pre>";
?>
Array
(
    [Host] => example.com
    [User-Agent] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...
    [Accept] => text/html,application/xhtml+xml,application/xml;q=0.9,...
    [X-Requested-With] => XMLHttpRequest
)

4. Безопасное использование данных из $_SERVER в выводе

При выводе любых данных из $_SERVER (например, User-Agent) обязательно применяется htmlspecialchars() для предотвращения XSS-атак. Пример с User-Agent:

Пример

<?php
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'неизвестно';
$safeUserAgent = htmlspecialchars($userAgent, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
echo "Ваш браузер: $safeUserAgent";
?>
Ваш браузер: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...

5. Логирование источника запроса в файл

Пример записи всех доступных данных в файл для последующего анализа:

Пример

<?php
$logData = [
    'time' => date('Y-m-d H:i:s'),
    'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
    'referer' => $_SERVER['HTTP_REFERER'] ?? 'none',
    'uri' => $_SERVER['REQUEST_URI'] ?? '/',
    'method' => $_SERVER['REQUEST_METHOD'] ?? 'GET',
    'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown',
];
file_put_contents('request_log.txt', json_encode($logData) . PHP_EOL, FILE_APPEND | LOCK_EX);
echo "Запись в лог выполнена";
?>
Запись в лог выполнена

Источник запроса в PHP - comments

En
Source query php (php)