¿Cuál es la diferencia entre HTTP_HOSTy SERVER_NAMEen PHP?
dónde:
HTTP_POST===$_SERVER['HTTP_HOST']SERVER_NAME===$_SERVER['SERVER_NAME']
¿Cuándo considerarías usar uno sobre el otro y por qué?
php
apache
server-variables
Emanuil Rusev
fuente
fuente

HTTP_HOST. De lo contrario, un atacante puede poner cualquier valor en laHost:solicitud de HTTP y hacer que el servidor lo acepte.$_SERVER['HTTP_HOST']o$_SERVER['SERVER_NAME']Respuestas:
Se
HTTP_HOSTobtiene del encabezado de solicitud HTTP y esto es lo que el cliente realmente utilizó como "host de destino" de la solicitud. ElSERVER_NAMEse define en la configuración del servidor. Cuál usar depende de para qué lo necesite. Sin embargo, ahora debe darse cuenta de que uno es un valor controlado por el cliente que, por lo tanto, puede no ser confiable para su uso en la lógica empresarial y el otro es un valor controlado por el servidor que es más confiable. Sin embargo, debe asegurarse de que el servidor web en cuestiónSERVER_NAMEesté configurado correctamente. Tomando Apache HTTPD como ejemplo, aquí hay un extracto de su documentación :Actualización : después de verificar la respuesta de Pekka en su pregunta que contiene un enlace a la respuesta de bobince para la que PHP siempre devolvería
HTTP_HOSTel valorSERVER_NAME, lo que va en contra de mi propia experiencia PHP 4.x + Apache HTTPD 1.2.x de hace un par de años , Soplé un poco de polvo de mi entorno XAMPP actual en Windows XP (Apache HTTPD 2.2.1 con PHP 5.2.8), lo inicié, creé una página PHP que imprime ambos valores, creé una aplicación de prueba JavaURLConnectionpara modificar elHostencabezado y las pruebas me enseñaron que este es (incorrectamente) el caso.Después de sospechar por primera vez PHP y buscar algunos informes de errores de PHP con respecto al tema, aprendí que la raíz del problema está en el servidor web utilizado, que devolvió HTTP incorrectamente
Hostencabezado cuandoSERVER_NAMEse solicitó. Así que busqué informes de errores HTTPD de Apache usando varias palabras clave relacionadas con el tema y finalmente encontré un error relacionado . Este comportamiento se introdujo desde alrededor de Apache HTTPD 1.3. Es necesario configurarUseCanonicalNamela directiva aonla<VirtualHost>entrada de laServerNameenhttpd.conf(consultar también la advertencia en la parte inferior del documento !).Esto funcionó para mí.
Resumido,
SERVER_NAMEes más confiable, ¡pero usted depende de la configuración del servidor!fuente
server_namedirectiva. Especialmente si noserver_namese establece, también_SERVER["SERVER_NAME"]estará vacío.HTTP_HOSTes el host de destino enviado por el cliente. Puede ser manipulado libremente por el usuario. No es problema enviar una solicitud a su sitio solicitando unHTTP_HOSTvalor dewww.stackoverflow.com.SERVER_NAMEproviene de laVirtualHostdefinición del servidor y, por lo tanto, se considera más confiable. Sin embargo, también puede manipularse desde el exterior en ciertas condiciones relacionadas con la configuración de su servidor web: consulte esta pregunta SO que trata los aspectos de seguridad de ambas variaciones.No debe confiar en ninguno para estar a salvo. Dicho esto, qué usar realmente depende de lo que quieras hacer. Si desea determinar en qué dominio se está ejecutando su script, puede usarlo con seguridad
HTTP_HOSTsiempre que los valores no válidos provenientes de un usuario malintencionado no puedan romper nada.fuente
UseCanonicalName onDebe usar en httpd.conf para forzarSERVER_NAMEa ser el nombre real del servidor.$_SERVER['SERVER_NAME']no funcionaría tan bien . Un servidor mal configurado se establecerá en$_SERVER['SERVER_NAME']función del valor de laHost:solicitud del cliente . Ambos son igualesComo mencioné en esta respuesta , si el servidor se ejecuta en un puerto que no sea 80 (como podría ser común en una máquina de desarrollo / intranet), entonces
HTTP_HOSTcontiene el puerto, mientrasSERVER_NAMEque no lo hace.(Al menos eso es lo que he notado en los hosts virtuales basados en el puerto de Apache)
Tenga en cuenta que
HTTP_HOSTno no contiene:443cuando se ejecuta en HTTPS (a no ser que se está ejecutando en un puerto no estándar, que no he probado).Como otros han señalado, los dos también difieren cuando se usa IPv6:
fuente
Tenga en cuenta que si quiere usar IPv6, probablemente quiera usarlo en
HTTP_HOSTlugar de hacerloSERVER_NAME. Si ingresahttp://[::1]/las variables de entorno serán las siguientes:Esto significa que si haces un mod_rewrite por ejemplo, podrías obtener un resultado desagradable. Ejemplo para una redirección SSL:
Esto aplica SOLO si accede al servidor sin un nombre de host.
fuente
https://%{SERVER_NAME}%{REQUEST_URI}Si desea verificar a través de un server.php o lo que sea, desea llamarlo con lo siguiente:
o
Luego acceda a él con todas las URL válidas para su sitio y compruebe la diferencia.
fuente
Depende de lo que quiera averiguar. SERVER_NAME es el nombre de host del servidor, mientras que HTTP_HOST es el host virtual al que se conectó el cliente.
fuente
SERVER_NAMEgeneralmente es el nombre del VirtualHost, no el servidor en sí. Y en Apache, aSERVER_NAMEmenudo se rellena con el mismo valor queHTTP_HOST(ver la respuesta de BalusC).SERVER_NAMEaplica a un host virtual. Sin embargo, todavía se puede usar una configuración de host virtual para un sitio. Muchas personas usan hosting compartido, así que entiendo tu punto.Me tomó un tiempo entender lo que la gente quería decir con "
SERVER_NAMEes más confiable". Uso un servidor compartido y no tengo acceso a las directivas de host virtual. Por lo tanto, uso mod_rewrite en.htaccesspara asignar diferentes correos electrónicosHTTP_HOSTa diferentes directorios. En ese caso, esHTTP_HOSTque tiene sentido.La situación es similar si se usan hosts virtuales basados en nombres: la
ServerNamedirectiva dentro de un host virtual simplemente dice qué nombre de host se asignará a este host virtual. La conclusión es que, en ambos casos, el nombre de host proporcionado por el cliente durante la solicitud (HTTP_HOST), debe coincidir con un nombre dentro del servidor, que se asigna a un directorio. Si el mapeo se realiza con directivas de host virtual o con reglas htaccess mod_rewrite es secundario aquí. En estos casos,HTTP_HOSTserá lo mismo queSERVER_NAME. Me alegra que Apache esté configurado de esa manera.Sin embargo, la situación es diferente con los hosts virtuales basados en IP. En este caso y solo en este caso,
SERVER_NAMEyHTTP_HOSTpuede ser diferente, porque ahora el cliente selecciona el servidor por la IP, no por el nombre. De hecho, puede haber configuraciones especiales donde esto es importante.Entonces, a partir de ahora, lo usaré
SERVER_NAME, en caso de que mi código se transfiera a estas configuraciones especiales.fuente
Suponiendo que uno tiene una configuración simple (CentOS 7, Apache 2.4.xy PHP 5.6.20) y solo un sitio web (sin asumir el alojamiento virtual) ...
En el sentido de PHP,
$_SERVER['SERVER_NAME']es un elemento que PHP registra en el$_SERVERsuperglobal basado en su configuración de Apache (**ServerName**directiva conUseCanonicalName On) en httpd.conf (ya sea desde un archivo de configuración de host virtual incluido, lo que sea, etc.). HTTP_HOST se deriva del HTTPhostencabezado . Tratar esto como entrada del usuario. Filtrar y validar antes de usar.Aquí hay un ejemplo de dónde lo uso
$_SERVER['SERVER_NAME']como base para una comparación. El siguiente método es de una clase secundaria concreta que hice nombradaServerValidator(child ofValidator).ServerValidatorcomprueba seis o siete elementos en $ _SERVER antes de usarlos.Al determinar si la solicitud HTTP es POST, utilizo este método.
Para cuando se llame a este método, todo el filtrado y la validación de los elementos relevantes de $ _SERVER habrían ocurrido (y el conjunto de propiedades relevantes).
La línea ...
... comprueba que el
$_SERVER['HTTP_HOST']valor (derivado en última instancia delhostencabezado HTTP solicitado ) coincida$_SERVER['SERVER_NAME'].Ahora, estoy usando hablan superglobal para explicar mi ejemplo, pero eso es sólo porque algunas personas no están familiarizados con
INPUT_GET,INPUT_POSTyINPUT_SERVERen lo que respecta afilter_input_array().La conclusión es, yo no manejo peticiones POST en mi servidor a menos que todos se cumplan cuatro condiciones. Por lo tanto, en términos de solicitudes POST, el hecho de no proporcionar un
hostencabezado HTTP (presencia probada para antes) significa fatalidad para los navegadores HTTP 1.0 estrictos . Por otra parte, el host solicitado debe coincidir con el valor deServerNameen el httpd.conf , y, por extensión, el valor de$_SERVER('SERVER_NAME')la$_SERVERsuperglobal. Una vez más, estaría usandoINPUT_SERVERlas funciones de filtro de PHP, pero me entiendes.Tenga en cuenta que Apache usa con frecuencia
ServerNameen redirecciones estándar (como dejar la barra diagonal fuera de una URL: por ejemplo, http://www.foo.com convirtiéndose en http://www.foo.com/ ), incluso si no está usando la reescritura de URL.Yo uso
$_SERVER['SERVER_NAME']como estándar, no$_SERVER['HTTP_HOST']. Hay mucho de ida y vuelta en este tema.$_SERVER['HTTP_HOST']podría estar vacío, por lo que esta no debería ser la base para crear convenciones de código como mi método público anterior. Pero, el hecho de que ambos se puedan configurar no garantiza que sean iguales. La prueba es la mejor manera de saberlo con certeza (teniendo en cuenta la versión de Apache y la versión de PHP).fuente
Como dijo BalusC, SERVER_NAME no es confiable y se puede cambiar en la configuración de Apache, la configuración del nombre del servidor y el firewall que puede estar entre usted y el servidor.
La siguiente función siempre devuelve el host real (host escrito por el usuario) sin puerto y es casi confiable:
fuente
$ _SERVER ['SERVER_NAME'] se basa en la configuración de sus servidores web. $ _SERVER ['HTTP_HOST'] se basa en la solicitud del cliente.
fuente