Qual é a diferença entre HTTP_HOST
e SERVER_NAME
no PHP?
Onde:
HTTP_POST
===$_SERVER['HTTP_HOST']
SERVER_NAME
===$_SERVER['SERVER_NAME']
Quando você consideraria usar um sobre o outro e por quê?
php
apache
server-variables
Emanuil Rusev
fonte
fonte
HTTP_HOST
. Caso contrário, um invasor pode atribuir qualquer valor àHost:
solicitação do HTTP e fazer com que o servidor a aceite.$_SERVER['HTTP_HOST']
ou$_SERVER['SERVER_NAME']
Respostas:
O
HTTP_HOST
é obtido no cabeçalho da solicitação HTTP e é isso que o cliente realmente usou como "host de destino" da solicitação. OSERVER_NAME
é definido na configuração do servidor. Qual deles usar depende do que você precisa. Agora, porém, você deve perceber que um é um valor controlado pelo cliente que pode, portanto, não ser confiável para uso na lógica de negócios e o outro é um valor controlado pelo servidor que é mais confiável. No entanto, você precisa garantir que o servidor da web em questão estejaSERVER_NAME
configurado corretamente. Tomando o Apache HTTPD como exemplo, aqui está um extrato de sua documentação :Atualização : depois de verificar a resposta de Pekka na sua pergunta, que contém um link para a resposta de bobince, pela qual o PHP sempre retornaria
HTTP_HOST
o valorSERVER_NAME
, o que contraria minhas próprias experiências com o PHP 4.x + Apache HTTPD 1.2.x de alguns anos atrás , Soprei um pouco de poeira do meu ambiente atual do XAMPP no Windows XP (Apache HTTPD 2.2.1 com PHP 5.2.8), iniciei-o, criei uma página PHP que imprime os dois valores, criei um aplicativo de teste Java usandoURLConnection
para modificar oHost
cabeçalho e testes me ensinaram que esse é realmente (incorretamente) o caso.Depois de suspeitar do PHP e pesquisar alguns relatórios de erros do PHP sobre o assunto, aprendi que a raiz do problema está no servidor da web usado, que retornou incorretamente o
Host
cabeçalho HTTP quandoSERVER_NAME
solicitado. Então, procurei nos relatórios de erros do Apache HTTPD usando várias palavras-chave relacionadas ao assunto e finalmente encontrei um bug relacionado . Esse comportamento foi introduzido desde o Apache HTTPD 1.3. Você precisa definirUseCanonicalName
directivaon
na<VirtualHost>
entrada doServerName
nahttpd.conf
(verifique também o aviso na parte inferior do documento !).Isso funcionou para mim.
Resumido,
SERVER_NAME
é mais confiável, mas você depende da configuração do servidor!fonte
server_name
diretiva. Especialmente se nãoserver_name
estiver definido, também_SERVER["SERVER_NAME"]
estará vazio.HTTP_HOST
é o host de destino enviado pelo cliente. Pode ser manipulado livremente pelo usuário. Não há problema em enviar uma solicitação ao seu site solicitando umHTTP_HOST
valor dewww.stackoverflow.com
.SERVER_NAME
vem daVirtualHost
definição do servidor e, portanto, é considerado mais confiável. No entanto, ele também pode ser manipulado externamente sob certas condições relacionadas à configuração do servidor da Web: Consulte esta pergunta SO que trata dos aspectos de segurança de ambas as variações.Você não deve confiar em nenhum deles para estar seguro. Dito isto, o que usar realmente depende do que você deseja fazer. Se você quiser determinar em qual domínio seu script está sendo executado, poderá usá-lo com segurança
HTTP_HOST
, desde que valores inválidos provenientes de um usuário mal-intencionado não possam quebrar nada.fonte
UseCanonicalName on
no httpd.conf para forçarSERVER_NAME
a ser o nome do servidor real.$_SERVER['SERVER_NAME']
também não funcionaria . Um servidor mal configurado será definido com$_SERVER['SERVER_NAME']
base no valor daHost:
solicitação do cliente . Ambos são iguais.Como mencionei nesta resposta , se o servidor for executado em uma porta diferente de 80 (como pode ser comum em uma máquina de desenvolvimento / intranet), ela
HTTP_HOST
conterá a porta, enquantoSERVER_NAME
não.(Pelo menos foi o que notei nos virtualhosts baseados em porta do Apache)
Observe que
HTTP_HOST
ele não contém:443
ao executar em HTTPS (a menos que você esteja executando em uma porta não padrão, que eu não testei).Como outros observaram, os dois também diferem ao usar o IPv6:
fonte
Observe que, se você deseja usar o IPv6, provavelmente deseja usá-lo em
HTTP_HOST
vez deSERVER_NAME
. Se você inserirhttp://[::1]/
as variáveis de ambiente, será o seguinte:Isso significa que, se você fizer um mod_rewrite, por exemplo, poderá obter um resultado desagradável. Exemplo para um redirecionamento SSL:
Isso se aplica SOMENTE se você acessar o servidor sem um nome de host.
fonte
https://%{SERVER_NAME}%{REQUEST_URI}
Se você deseja verificar através de um server.php ou o que quer, você pode chamá-lo com o seguinte:
ou
Em seguida, acesse-o com todos os URLs válidos para o seu site e confira a diferença.
fonte
Depende do que eu quero descobrir. SERVER_NAME é o nome do host do servidor, enquanto HTTP_HOST é o host virtual ao qual o cliente se conectou.
fonte
SERVER_NAME
geralmente é o nome do VirtualHost, não o próprio servidor. E no Apache,SERVER_NAME
geralmente é preenchido com o mesmo valor queHTTP_HOST
(consulte a resposta do BalusC).SERVER_NAME
se aplica a um host virtual. No entanto, ainda é possível usar uma configuração de host virtual para um site. Muitas pessoas usam hospedagem compartilhada, então eu entendo o seu ponto.Demorei um pouco para entender o que as pessoas queriam dizer com '
SERVER_NAME
é mais confiável'. Eu uso um servidor compartilhado e não tem acesso a diretivas de host virtual. Então, eu uso mod_rewrite.htaccess
para mapearHTTP_HOST
s diferentes para diretórios diferentes. Nesse caso, éHTTP_HOST
que é significativo.A situação é semelhante se alguém usar hosts virtuais baseados em nome: a
ServerName
diretiva em um host virtual simplesmente diz qual nome do host será mapeado para esse host virtual. A conclusão é que, em ambos os casos, o nome do host fornecido pelo cliente durante a request (HTTP_HOST
) deve corresponder a um nome no servidor, que é mapeado para um diretório. Se o mapeamento é feito com diretivas de host virtual ou com regras htaccess mod_rewrite, é secundário aqui. Nestes casos,HTTP_HOST
será o mesmo queSERVER_NAME
. Fico feliz que o Apache esteja configurado dessa maneira.No entanto, a situação é diferente com hosts virtuais baseados em IP. Nesse caso, e somente neste caso,
SERVER_NAME
eHTTP_HOST
pode ser diferente, porque agora o cliente seleciona o servidor pelo IP, não pelo nome. De fato, pode haver configurações especiais onde isso é importante.Então, a partir de agora, usarei
SERVER_NAME
, caso meu código seja portado nessas configurações especiais.fonte
Supondo que um tenha uma configuração simples (CentOS 7, Apache 2.4.xe PHP 5.6.20) e apenas um site (não assumindo hospedagem virtual) ...
No sentido PHP,
$_SERVER['SERVER_NAME']
é um elemento que o PHP registra no$_SERVER
superglobal com base na sua configuração do Apache (**ServerName**
diretiva comUseCanonicalName On
) no httpd.conf (seja de um arquivo de configuração do host virtual incluído, o que seja, etc ...). HTTP_HOST é derivado do HTTPhost
cabeçalho . Trate isso como entrada do usuário. Filtre e valide antes de usar.Aqui está um exemplo de onde eu uso
$_SERVER['SERVER_NAME']
como base para uma comparação. O método a seguir é de uma classe filho concreta que eu criei chamadaServerValidator
(filho deValidator
).ServerValidator
verifica seis ou sete elementos em $ _SERVER antes de usá-los.Para determinar se a solicitação HTTP é POST, eu uso esse método.
Quando esse método é chamado, toda a filtragem e validação dos elementos $ _SERVER relevantes já teriam ocorrido (e as propriedades relevantes foram definidas).
A linha ...
... verifica se o
$_SERVER['HTTP_HOST']
valor (finalmente derivado dohost
cabeçalho HTTP solicitado ) corresponde$_SERVER['SERVER_NAME']
.Agora, eu estou usando falar superglobal para explicar o meu exemplo, mas isso é apenas porque algumas pessoas não estão familiarizados com
INPUT_GET
,INPUT_POST
eINPUT_SERVER
no que diz respeito afilter_input_array()
.A conclusão é que não lida com solicitações POST no meu servidor, a menos que todas as quatro condições sejam atendidas. Por isso, em termos de solicitações POST, a incapacidade de fornecer um HTTP
host
cabeçalho (presença testado para anteriores) períodos DooM para rigorosas HTTP 1.0 navegadores. Além disso, o anfitrião solicitado deve corresponder ao valor deServerName
no httpd.conf , e, por extensão, o valor para$_SERVER('SERVER_NAME')
no$_SERVER
superglobal. Mais uma vez, eu usariaINPUT_SERVER
com as funções de filtro PHP, mas você entendeu a minha deriva.Lembre-se de que o Apache costuma usar
ServerName
em redirecionamentos padrão (como deixar a barra à direita de uma URL: exemplo, http://www.foo.com se torna http://www.foo.com/ ), mesmo que você não esteja usando a reescrita de URL.Eu uso
$_SERVER['SERVER_NAME']
como padrão, não$_SERVER['HTTP_HOST']
. Há muitas discussões sobre esse assunto.$_SERVER['HTTP_HOST']
pode estar vazio, portanto, essa não deve ser a base para a criação de convenções de código, como meu método público acima. Mas, apenas porque ambos podem ser definidos, não garante que serão iguais. Testar é a melhor maneira de ter certeza (tendo em mente a versão Apache e a versão PHP).fonte
Como o balusC disse que SERVER_NAME não é confiável e pode ser alterado na configuração do apache, na configuração do nome do servidor e no firewall que pode estar entre você e o servidor.
A função a seguir sempre retorna o host real (host digitado pelo usuário) sem porta e é quase confiável:
fonte
$ _SERVER ['SERVER_NAME'] se baseia na configuração dos seus servidores web. $ _SERVER ['HTTP_HOST'] é baseado na solicitação do cliente.
fonte