В чем разница между HTTP_HOST
и SERVER_NAME
в PHP?
где:
HTTP_POST
===$_SERVER['HTTP_HOST']
SERVER_NAME
===$_SERVER['SERVER_NAME']
Когда вы рассмотрите возможность использования одного над другим и почему?
php
apache
server-variables
Эмануил Русев
источник
источник
HTTP_HOST
. В противном случае злоумышленник может ввести любое значение вHost:
запрос HTTP и заставить сервер принять его.$_SERVER['HTTP_HOST']
или$_SERVER['SERVER_NAME']
Ответы:
HTTP_HOST
Получается из заголовка запроса HTTP , и это то , что клиент на самом деле используется в качестве «целевого хоста» запроса. ЭтоSERVER_NAME
определяется в конфигурации сервера. Какой из них использовать, зависит от того, для чего он вам нужен. Однако теперь вы должны понимать, что одно является контролируемым клиентом значением, которое, таким образом, может быть ненадежным для использования в бизнес-логике, а другое - управляемым сервером значением, которое является более надежным. Однако вам необходимо убедиться, что данный веб-серверSERVER_NAME
правильно настроен. Взяв Apache HTTPD в качестве примера, вот выдержка из его документации :Обновление : после проверки ответа Пекки на ваш вопрос, который содержит ссылку на ответ Бобинса, для которого PHP всегда будет возвращать
HTTP_HOST
значениеSERVER_NAME
, что противоречит моему собственному опыту PHP 4.x + Apache HTTPD 1.2.x, накопленному пару лет назад. Я выплеснул немного пыли из моей текущей среды XAMPP в Windows XP (Apache HTTPD 2.2.1 с PHP 5.2.8), запустил его, создал страницу PHP, которая печатает оба значения, создал тестовое приложение Java, используяURLConnection
для измененияHost
заголовка и тесты научили меня, что это действительно (неправильно) дело.После того, как я впервые заподозрил PHP и покопался в некоторых отчетах об ошибках PHP по этой теме, я узнал, что корень проблемы в используемом веб-сервере, что он неверно возвращал HTTP-
Host
заголовок приSERVER_NAME
запросе. Поэтому я копался в отчетах об ошибках Apache HTTPD, используя различные ключевые слова по теме, и в конце концов обнаружил связанную ошибку . Такое поведение было введено начиная с Apache HTTPD 1.3. Вам нужно установитьUseCanonicalName
директивыon
в<VirtualHost>
записи оServerName
дюймеhttpd.conf
(также проверить предупреждение в нижней части документа !).Это сработало для меня.
Подведем итог,
SERVER_NAME
это более надежно, но вы зависите от конфигурации сервера!источник
server_name
директивой. Особенно, если неserver_name
установлено и_SERVER["SERVER_NAME"]
будет пустым.HTTP_HOST
целевой хост, отправленный клиентом. Это может свободно управляться пользователем. Это не проблема, чтобы отправить запрос на ваш сайт с просьбой оHTTP_HOST
значенииwww.stackoverflow.com
.SERVER_NAME
исходит из определения сервераVirtualHost
и поэтому считается более надежным. Однако им также можно манипулировать извне при определенных условиях, связанных с настройкой вашего веб-сервера: см. Этот вопрос SO, в котором рассматриваются аспекты безопасности обоих вариантов.Вы не должны полагаться ни на то, чтобы быть в безопасности. Тем не менее, что использовать на самом деле зависит от того, что вы хотите сделать. Если вы хотите определить, в каком домене работает ваш скрипт, вы можете безопасно использовать его,
HTTP_HOST
если недопустимые значения, исходящие от злонамеренного пользователя, не могут ничего сломать.источник
UseCanonicalName on
в httpd.conf, чтобы заставитьSERVER_NAME
быть фактическим именем сервера.$_SERVER['SERVER_NAME']
также не будет работать . Плохо настроенный сервер будет установлен$_SERVER['SERVER_NAME']
на основе значенияHost:
запроса клиента . Оба равны.Как я уже упоминал в этом ответе , если сервер работает на порте, отличном от 80 (как это может быть распространено на машине разработки / интрасети), то он
HTTP_HOST
содержит порт, аSERVER_NAME
не -.(По крайней мере, это то, что я заметил в виртуальных хостах на основе портов Apache)
Обратите внимание , что
HTTP_HOST
это не содержит:443
при работе на HTTPS (если вы не работаете на нестандартном порту, который я не проверял).Как уже отмечали другие, эти два также отличаются при использовании IPv6:
источник
Обратите внимание, что если вы хотите использовать IPv6, вы, вероятно, хотите использовать
HTTP_HOST
вместоSERVER_NAME
. Если вы введетеhttp://[::1]/
переменные окружения будут следующими:Это означает, что если вы сделаете mod_rewrite, например, вы можете получить неприятный результат. Пример для перенаправления SSL:
Это относится ТОЛЬКО если вы обращаетесь к серверу без имени хоста.
источник
https://%{SERVER_NAME}%{REQUEST_URI}
Если вы хотите проверить через server.php или что-то еще, вы должны вызвать его с помощью следующего:
или
Затем получите доступ ко всем действительным URL-адресам вашего сайта и проверьте разницу.
источник
Зависит от того, что я хочу узнать. SERVER_NAME - это имя хоста сервера, а HTTP_HOST - это виртуальный хост, к которому подключен клиент.
источник
SERVER_NAME
обычно это имя VirtualHost, а не сам сервер. А в ApacheSERVER_NAME
часто заполняется тем же значением, что иHTTP_HOST
(см. Ответ BalusC).SERVER_NAME
относится к виртуальному хосту. Однако можно по-прежнему использовать настройку виртуального хоста для одного сайта. Многие люди используют виртуальный хостинг, поэтому я понимаю вашу точку зрения.Мне потребовалось некоторое время, чтобы понять, что люди подразумевают под «
SERVER_NAME
более надежным». Я использую общий сервер и не имею доступа к директивам виртуального хоста. Итак, я использую mod_rewrite,.htaccess
чтобы отобразить разныеHTTP_HOST
s в разные каталоги. В этом случае, этоHTTP_HOST
имеет значение.Ситуация аналогична, если использовать виртуальные хосты на основе имен:
ServerName
директива внутри виртуального хоста просто говорит, какое имя хоста будет сопоставлено с этим виртуальным хостом. Суть в том, что в обоих случаях имя хоста, предоставленное клиентом во время request (HTTP_HOST
), должно совпадать с именем на сервере, которое само сопоставлено с каталогом. Независимо от того, выполняется ли сопоставление с директивами виртуального хоста или с правилами htaccess mod_rewrite, здесь второстепенно. В этих случаяхHTTP_HOST
будет так же, какSERVER_NAME
. Я рад, что Apache настроен таким образом.Однако ситуация с виртуальными хостами на основе IP отличается. В этом случае и только в этом случае,
SERVER_NAME
иHTTP_HOST
могут быть разными, потому что теперь клиент выбирает сервер по IP, а не по имени. Действительно, могут быть специальные конфигурации, где это важно.Итак, начиная с этого момента, я буду использовать
SERVER_NAME
, на всякий случай, если мой код перенесен в эти специальные конфигурации.источник
Предполагая, что у вас есть простая установка (CentOS 7, Apache 2.4.x и PHP 5.6.20) и только один веб-сайт (без виртуального хостинга) ...
В смысле PHP,
$_SERVER['SERVER_NAME']
это элемент, который PHP регистрирует в$_SERVER
суперглобале на основе вашей конфигурации Apache (**ServerName**
директива сUseCanonicalName On
) в httpd.conf (будь то из включенного файла конфигурации виртуального хоста, что угодно, и т. Д.). HTTP_HOST является производным отhost
заголовка HTTP . Относитесь к этому как к пользовательскому вводу. Фильтруйте и проверяйте перед использованием.Вот пример, где я использую
$_SERVER['SERVER_NAME']
в качестве основы для сравнения. Следующий метод взят из конкретного дочернего класса, который я создал namedServerValidator
(child ofValidator
).ServerValidator
проверяет шесть или семь элементов в $ _SERVER перед их использованием.При определении, является ли HTTP-запрос POST, я использую этот метод.
Ко времени вызова этого метода все фильтрация и проверка соответствующих элементов $ _SERVER должны были произойти (и установить соответствующие свойства).
Линия ...
... проверяет, что
$_SERVER['HTTP_HOST']
значение (в конечном счете полученное из запрошенногоhost
заголовка HTTP) совпадает$_SERVER['SERVER_NAME']
.Теперь я использую суперглобальном Speak объяснить мой пример, но это только потому , что некоторые люди не знакомы с
INPUT_GET
,INPUT_POST
иINPUT_SERVER
в отношении кfilter_input_array()
.Суть в том, что я не обрабатываю POST-запросы на моем сервере, если не выполнены все четыре условия. Следовательно, с точки зрения запросов POST, неспособность предоставить
host
заголовок HTTP (наличие проверено на более ранние версии) означает гибель для строгих браузеров HTTP 1.0 . Кроме того, запрашиваемый хост должен совпадать со значением дляServerName
в httpd.conf , и, расширением, значение для$_SERVER('SERVER_NAME')
в$_SERVER
суперглобальный. Опять же, я буду использоватьINPUT_SERVER
функции фильтра PHP, но вы поймете мой дрейф.Имейте в виду , что Apache часто используется
ServerName
в стандартных редиректов (например, оставляя слэш от URL - адрес: Пример, http://www.foo.com становится http://www.foo.com/ ), даже если вы не используя переписывание URL.Я использую
$_SERVER['SERVER_NAME']
как стандарт, а не$_SERVER['HTTP_HOST']
. Существует много вопросов по этому вопросу.$_SERVER['HTTP_HOST']
может быть пустым, так что это не должно быть основой для создания соглашений кода, таких как мой публичный метод выше. Но только то, что оба могут быть установлены, не гарантирует, что они будут равны. Тестирование - лучший способ узнать наверняка (с учетом версии Apache и версии PHP).источник
Как сообщает balusC, имя SERVER_NAME ненадежно и может быть изменено в конфигурации apache, конфигурации имени сервера для сервера и брандмауэра, которые могут находиться между вами и сервером.
Следующая функция всегда возвращает реальный хост (введенный пользователем хост) без порта, и это почти надежно:
источник
$ _SERVER ['SERVER_NAME'] зависит от конфигурации ваших веб-серверов. $ _SERVER ['HTTP_HOST'] основан на запросе от клиента.
источник