В чем разница между хостом HTTP и именем сервера в PHP?
когда бы вы подумали об использовании одного над другим и почему?
9 ответов:
The
HTTP_HOST
полученные от заголовок HTTP-запроса и это то, что клиент фактически использовал в качестве "целевого хоста" запроса. ЭлементSERVER_NAME
определен в конфигурации сервера. Какой из них использовать, зависит от того, для чего он вам нужен. Однако теперь вы должны понимать, что один из них является контролируемым клиентом значением, которое, таким образом, может быть ненадежным для использования в бизнес-логике, а другой-контролируемым сервером значением, которое является более надежным. Однако вам необходимо убедиться, что веб-сервер в вопрос имеет значениеSERVER_NAME
правильно настроен. Принимая Apache HTTPD в качестве примера, вот выдержка из документация:, если не
ServerName
указывается, затем сервер пытается вывести имя хоста, выполнив обратный поиск по IP-адресу. Если порт не указан вServerName
, то сервер будет использовать порт из входящего запроса. Для оптимальной надежности и предсказуемости необходимо указать явное имя хоста и порт используя bobince это что PHP всегда будет возвращатьHTTP_HOST
' s значение для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
(также проверьте предупреждение в нижней части документ!).<VirtualHost *> ServerName example.com UseCanonicalName on </VirtualHost>
это работает для меня.
суммированный,
SERVER_NAME
надежнее, но ты зависимая на настройки сервера!
HTTP_HOST
является целевым хостом, отправленным клиентом. Им можно манипулировать свободно потребителем. Это не проблема, чтобы отправить запрос на ваш сайт, прошуHTTP_HOST
стоимостьюwww.stackoverflow.com
.
SERVER_NAME
исходит от сервераVirtualHost
определение и поэтому считается более надежным. Однако он также может управляться извне при определенных условиях, связанных с настройкой вашего веб-сервера: см. Это это так вопрос что касается аспекты безопасности обоих вариантов.вы не должны полагаться ни на то, чтобы быть в безопасности. Тем не менее, что использовать на самом деле зависит от того, что вы хотите сделать. Если вы хотите определить, на каком домене работает ваш скрипт, вы можете безопасно использовать
HTTP_HOST
пока недопустимые значения, поступающие от вредоносного пользователя, ничего не могут сломать.
как я уже упоминал в ответ, если сервер работает на порту, отличном от 80 (что может быть распространено на машине разработки / интрасети), то
HTTP_HOST
содержит порт, в то время какSERVER_NAME
нет.$_SERVER['HTTP_HOST'] == 'localhost:8080' $_SERVER['SERVER_NAME'] == 'localhost'
(по крайней мере, это то, что я заметил в Apache port-based virtualhosts)
отметим, что
HTTP_HOST
тут не содержат:443
при работе на HTTPS (если вы не работаете на нестандартном порту, которого у меня нет проверенный.)как отмечали другие, они также отличаются при использовании IPv6:
$_SERVER['HTTP_HOST'] == '[::1]' $_SERVER['SERVER_NAME'] == '::1'
обратите внимание, что если вы хотите Использовать IPv6, вы, вероятно, хотите использовать
HTTP_HOST
, а неSERVER_NAME
. Если вы введетеhttp://[::1]/
переменные среды будут следующими:HTTP_HOST = [::1] SERVER_NAME = ::1
это означает, что если вы делаете mod_rewrite например, вы можете получить неприятный результат. Пример для перенаправления SSL:
# SERVER_NAME will NOT work - Redirection to https://::1/ RewriteRule .* https://%{SERVER_NAME}/ # HTTP_HOST will work - Redirection to https://[::1]/ RewriteRule .* https://%{HTTP_HOST}/
это применимо только при доступе к серверу без имени хоста.
Если вы хотите проверить через сервер.php или как вы хотите его назвать со следующим:
<?php phpinfo(INFO_VARIABLES); ?>
или
<?php header("Content-type: text/plain"); print_r($_SERVER); ?>
затем открыть его с допустимым URL-адреса для вашего сайта и проверить разницу.
зависит от того, что я хочу узнать. SERVER_NAME-это имя хоста сервера, а HTTP_HOST-виртуальный хост, к которому подключен клиент.
мне потребовалось некоторое время, чтобы понять, что человек имел в виду '
SERVER_NAME
более надежный. Я использую общий сервер и не имею доступа к директивам виртуального хоста. Итак, я использую mod_rewrite в.htaccess
для отображения различныхHTTP_HOST
s в разных каталогах. В таком случае, этоHTTP_HOST
что имеет смысл.ситуация аналогична, если использовать виртуальные хосты на основе имен:
ServerName
директива внутри виртуального хоста просто говорит, Какое имя хоста будет сопоставлено с этим виртуальным хостом. Суть в том, что в обоих случаях имя хоста, предоставленное клиентом во время запроса (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
superglobal на основе конфигурации Apache (. Рассматривайте это как пользователя вход. Фильтруйте и проверяйте перед использованием.вот пример, где я использую
$_SERVER['SERVER_NAME']
как основа для сравнения. Следующий метод из конкретного дочернего класса я сделал с именемServerValidator
(ребенокValidator
).ServerValidator
проверяет шесть или семь элементов в $_SERVER перед их использованием.при определении того, является ли HTTP-запрос POST, я использую этот метод.
public function isPOST() { return (($this->requestMethod === 'POST') && // Ignore $this->hasTokenTimeLeft() && // Ignore $this->hasSameGETandPOSTIdentities() && // Ingore ($this->httpHost === filter_input(INPUT_SERVER, 'SERVER_NAME'))); }
к моменту вызова этого метода все фильтрации и проверки соответствующих $_SERVER элементы произошли бы (и соответствующий набор свойств).
линии ...
($this->httpHost === filter_input(INPUT_SERVER, 'SERVER_NAME')
... проверяет, что
$_SERVER['HTTP_HOST']
значение (в конечном счете, полученное из запрошенногоhost
HTTP заголовок) соответствует$_SERVER['SERVER_NAME']
.теперь я использую superglobal speak, чтобы объяснить мой пример, но это только потому, что некоторые люди не знакомы с
INPUT_GET
,INPUT_POST
иINPUT_SERVER
в отношенииfilter_input_array()
.суть в том, что я делаю не обрабатывать запросы POST на моем сервере, если все выполняются четыре условия. Следовательно, с точки зрения запросов POST, неспособность предоставить HTTP
host
заголовок (наличие проверено на более ранние) заклинания doom строго HTTP 1.0 - браузеры. Более того, запрошенный хост должно соответствовать значению наServerName
на httpd.conf, и, по расширению, значение для$_SERVER('SERVER_NAME')
на$_SERVER
суперглобальная. Опять Же, Я будет использоватьINPUT_SERVER
с функциями фильтра PHP, но вы ловите мой дрейф.имейте в виду, что Apache часто используется
ServerName
in стандартные редиректы (например, оставляя конечную косую черту с 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 , имя сервера конфигурации сервера и брандмауэра, который может быть между вами и сервером.
следующая функция всегда возвращает реальный хост (пользовательский тип хоста) без порта, и это почти надежно:
function getRealHost(){ list($realHost,)=explode(':',$_SERVER['HTTP_HOST']); return $realHost; }