Источник запроса в PHP: откуда пришел пользователь и какие параметры переданы
Основные подходы к получению источника запроса
В 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'] и добавлять его при необходимости.
Расширенные примеры работы с источником запроса
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 "Запись в лог выполнена";
?>
Запись в лог выполнена