Pergunta

Quando você consideraria usar um em vez do outro e por quê?

Foi útil?

Solução

o HTTP_HOST é obtido do Cabeçalho de solicitação HTTP E é isso que o cliente realmente usou como "host de destino" da solicitação. o SERVER_NAME é definido na configuração do servidor. Para qual usar depende do que você precisa. Agora, no entanto, você deve perceber que um é um valor controlado pelo cliente que, portanto, pode não ser confiável para uso na lógica de negócios e o outro é um valor controlado por servidor que é mais confiável. No entanto, você precisa garantir que o servidor da web em questão tenha o SERVER_NAME configurado corretamente. Tomando o apache httpd como exemplo, aqui está um extrato de sua documentação:

Se não ServerName é especificado, o servidor tenta deduzir o nome do host, executando uma pesquisa reversa no endereço IP. Se nenhuma porta for especificada no ServerName, o servidor usará a porta da solicitação de entrada. Para uma confiabilidade e previsibilidade ideais, você deve especificar um nome de host explícito e porta usando o ServerName diretivo.


Atualizar: Depois de checar A resposta de Pekka em sua pergunta que contém um link para Resposta de Bobince Esse PHP sempre retornaria HTTP_HOSTé o valor para SERVER_NAME, que vai contra o meu próprio PHP 4.x + apache httpd 1.2.x experiências de alguns anos atrás, soprei um pouco de poeira do meu ambiente XAMPP atual no Windows XP (Apache HTTPD 2.2.1 com Php 5.2.8), iniciado Ele criou uma página PHP que imprime os dois valores, criou um aplicativo de teste Java usando URLConnection Para modificar o Host O cabeçalho e os testes me ensinaram que esse é realmente (incorretamente) o caso.

Depois de suspeitar de PHP e cavar em alguns Relatórios de bug php Em relação ao assunto, aprendi que a raiz do problema é usada no servidor da web, que ele retornou incorretamente HTTP Host cabeçalho quando SERVER_NAME foi solicitado. Então eu cavei Relatórios de bug httpd apache usando várias palavras -chave em relação ao assunto e finalmente encontrei um bug relacionado. Esse comportamento foi introduzido desde o Apache HTTPD 1.3. Você precisa definir UseCanonicalName diretiva para on no <VirtualHost> entrada do ServerName dentro httpd.conf (verifique também o aviso na parte inferior de o documento!).

<VirtualHost *>
    ServerName example.com
    UseCanonicalName on
</VirtualHost> 

Isso funcionou para mim.

Resumido, SERVER_NAME é mais confiável, mas você é dependente Na configuração do servidor!

Outras dicas

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 pedindo um HTTP_HOST valor de www.stackoverflow.com.

SERVER_NAME vem do servidor VirtualHost definição e, portanto, é considerado mais confiável. No entanto, pode ser manipulado de fora, sob certas condições relacionadas à forma como seu servidor da web está configurado: veja isso Isso é tão pergunta Isso lida com os aspectos de segurança de ambas as variações.

Você não deve confiar em nenhum dos dois para estar seguro. Dito isto, o que usar realmente depende do que você deseja fazer. Se você deseja determinar em qual domínio seu script está em execução, você pode usar com segurança HTTP_HOST Enquanto os valores inválidos provenientes de um usuário malicioso não poderão quebrar nada.

Como mencionei em esta resposta, se o servidor executar em uma porta que não seja 80 (como pode ser comum em uma máquina de desenvolvimento/intranet), então HTTP_HOST contém a porta, enquanto SERVER_NAME não.

$_SERVER['HTTP_HOST'] == 'localhost:8080'
$_SERVER['SERVER_NAME'] == 'localhost'

(Pelo menos foi o que eu notei no virtualhosts baseados em portas Apache)

Observe que HTTP_HOST faz não conter :443 Ao executar em HTTPS (a menos que você esteja executando em uma porta fora do padrão, que eu não testei).

Como outros observaram, os dois também diferem ao usar o IPv6:

$_SERVER['HTTP_HOST'] == '[::1]'
$_SERVER['SERVER_NAME'] == '::1'

Observe que se você quiser usar IPv6, provavelmente desejará usar HTTP_HOST em vez de SERVER_NAME .Se você entrar http://[::1]/ as variáveis ​​de ambiente serão as seguintes:

HTTP_HOST = [::1]
SERVER_NAME = ::1

Isso significa que se você fizer um mod_rewrite, por exemplo, poderá obter um resultado desagradável.Exemplo de redirecionamento 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}/

Isto se aplica SOMENTE se você acessar o servidor sem um nome de host.

Se você deseja verificar através de um servidor.php ou o que deseja chamá -lo com o seguinte:

<?php

phpinfo(INFO_VARIABLES);

?>

ou

<?php

header("Content-type: text/plain");

print_r($_SERVER);

?>

Em seguida, acesse -o com todos os URLs válidos para o seu site e confira a diferença.

Depende do que eu quero descobrir. Server_name é o nome do host do servidor, enquanto http_host é o host virtual ao qual o cliente conectou.

Demorei um pouco para entender o que as pessoas queriam dizer 'SERVER_NAME é mais confiável '. Eu uso um servidor compartilhado e não tenho acesso a diretivas de host virtuais. Então, eu uso mod_rewrite em .htaccess para mapear diferente HTTP_HOSTs para diretórios diferentes. Nesse caso, é HTTP_HOST Isso é significativo.

A situação é semelhante se alguém usa hosts virtuais baseados em nomes: o ServerName A diretiva em um host virtual simplesmente diz qual nome de host será mapeado para este host virtual. O ponto principal é que, em ambos os casos, o nome do host fornecido pelo cliente durante a solicitação (HTTP_HOST), deve ser correspondido a um nome no servidor, que é mapeado para um diretório. Se o mapeamento é feito com as diretrizes do host virtual ou com as regras htaccess mod_rewrite é secundária aqui. Nesses casos, HTTP_HOST será o mesmo que SERVER_NAME. Fico feliz que o Apache esteja configurado dessa maneira.

No entanto, a situação é diferente com hosts virtuais baseados em IP. Neste caso e somente neste caso, SERVER_NAME e HTTP_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, vou usar SERVER_NAME, caso meu código seja portado nessas configurações especiais.

Supondo que alguém tenha uma configuração simples (CentOS 7, Apache 2.4.x e Php 5.6.20) e apenas um site (não assumindo hospedagem virtual) ...

No sentido do PHP, $_SERVER['SERVER_NAME'] é um elemento PHP registra no $_SERVER Superglobal com base na sua configuração do Apache (**ServerName** diretiva com UseCanonicalName On ) em httpd.conf (seja de um arquivo de configuração do host virtual incluído, qualquer que seja, etc ...). Http_host é derivado do HTTP host 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 infantil concreta que eu fiz nomeado ServerValidator (Filho de Validator). ServerValidator Verifica seis ou sete elementos em $ _Server antes de usá -los.

Ao determinar se a solicitação HTTP está postagem, eu uso esse método.

public function isPOST()
{
    return (($this->requestMethod === 'POST')    &&  // Ignore
            $this->hasTokenTimeLeft()            &&  // Ignore
            $this->hasSameGETandPOSTIdentities() &&  // Ingore
            ($this->httpHost === filter_input(INPUT_SERVER, 'SERVER_NAME')));
}

Quando esse método é chamado, toda a filtragem e validação de elementos relevantes de $ _erver teriam ocorrido (e conjunto de propriedades relevantes).

A linha ...

($this->httpHost === filter_input(INPUT_SERVER, 'SERVER_NAME')

... verifica se o $_SERVER['HTTP_HOST'] valor (em última análise, derivado do solicitado host Cabeçalho HTTP) Matches $_SERVER['SERVER_NAME'].

Agora, estou usando superglobal falar para explicar meu exemplo, mas isso é apenas porque algumas pessoas não estão familiarizadas com INPUT_GET, INPUT_POST, e INPUT_SERVER em relação a filter_input_array().

A linha inferior é, não lide com solicitações de postagem no meu servidor, a menos que tudo Quatro condições são atendidas. Portanto, em termos de solicitações de postagens, não fornecer um HTTP host Cabeçalho (presença testada para anteriores) Feitiços ruína para rigoroso HTTP 1.0 navegadores. Além disso, o host solicitado deve corresponder ao valor por ServerName no httpd.conf, e, por extensão, o valor para $_SERVER('SERVER_NAME') no $_SERVER superglobal. Novamente, eu estaria usando INPUT_SERVER Com as funções do filtro PHP, mas você pega minha deriva.

Lembre -se de que o Apache frequentemente usa ServerName dentro redirecionamentos padrão (como deixar o corte de um URL: Exemplo, http://www.foo.com tornando-se http://www.foo.com/), mesmo se você não estiver usando a reescrita de URL.

eu uso $_SERVER['SERVER_NAME'] Como padrão, não $_SERVER['HTTP_HOST']. Há muito sobre esse assunto. $_SERVER['HTTP_HOST'] Pode estar vazio, portanto, essa não deve ser a base para criar convenções de código, como meu método público acima. Mas, apenas porque ambos podem ser definidos não garantem que serão iguais. O teste é a melhor maneira de saber com certeza (tendo em mente a versão Apache e a versão PHP).

Como o Balusc, o servidor_name não é confiável e pode ser alterado na configuração do Apache, a configuração do nome do servidor do servidor e do 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:

function getRealHost(){
   list($realHost,)=explode(':',$_SERVER['HTTP_HOST']);
   return $realHost;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top