В чем разница между хостом HTTP и именем сервера в PHP?
когда вы рассмотрите возможность использования одного над другим и почему?
9 ответов
на HTTP_HOST
полученные от заголовок HTTP-запроса и это то, что клиент фактически использовал в качестве" целевого хоста " запроса. The SERVER_NAME
определен в конфигурации сервера. Какой из них использовать, зависит от того, для чего он вам нужен. Однако теперь вы должны понимать, что одно из них-контролируемое клиентом значение, которое может быть ненадежным для использования в бизнес-логике, а другое-контролируемое сервером значение, которое является более надежным. Однако вам необходимо убедиться, что веб-сервер в вопрос имеет SERVER_NAME
правильно настроен. Принимая Apache HTTPD в качестве примера, вот выдержка из документация:
, если не
ServerName
указывается, затем сервер пытается вывести имя хоста, выполнив обратный поиск по IP-адресу. Если порт не указан вServerName
, затем сервер будет использовать порт из входящего запроса. Для оптимальной надежности и предсказуемости необходимо указать явное имя хоста и порт с помощью bobince это что 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
(также проверьте предупреждение в нижней части документ!).<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'
(по крайней мере, это то, что я заметил в virtualhosts на основе портов Apache)
отметим, что 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-адреса для вашего сайта и проверить разницу.
зависит от того, что я хочу узнать. ИМЯ_СЕРВЕРА - это имя хоста сервера, а 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 (. Рассматривайте это как user вход. Фильтровать и проверять перед использованием.
вот пример того, где я использую $_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
на стандартные редиректы (например, оставляя конечную косую черту с URL: пример, http://www.foo.com становление http://www.foo.com/), даже если вы не используете перезапись URL.
я использую $_SERVER['SERVER_NAME']
как стандарт, не $_SERVER['HTTP_HOST']
. Есть много и далее по этому вопросу. $_SERVER['HTTP_HOST']
может быть пустым, поэтому это не должно быть основой для создания соглашений кода, таких как мой открытый метод выше. Но только потому, что оба могут быть установлены, не гарантирует, что они будут равны. Тестирование-лучший способ узнать наверняка (с учетом версии Apache и версии PHP).
как balusC сказал ИМЯ_СЕРВЕРА не является надежным и может быть изменен в конфигурации apache , имя сервера конфигурации сервера и брандмауэра, который может быть между вами и сервером.
следующая функция всегда возвращает реальный хост (типизированный пользователем хост) без порта, и это почти надежно:
function getRealHost(){
list($realHost,)=explode(':',$_SERVER['HTTP_HOST']);
return $realHost;
}