¿Cuál es la diferencia entre HTTP_HOST
y SERVER_NAME
en 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_HOST
obtiene del encabezado de solicitud HTTP y esto es lo que el cliente realmente utilizó como "host de destino" de la solicitud. ElSERVER_NAME
se 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_NAME
esté 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_HOST
el 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 JavaURLConnection
para modificar elHost
encabezado 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
Host
encabezado cuandoSERVER_NAME
se 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 configurarUseCanonicalName
la directiva aon
la<VirtualHost>
entrada de laServerName
enhttpd.conf
(consultar también la advertencia en la parte inferior del documento !).Esto funcionó para mí.
Resumido,
SERVER_NAME
es más confiable, ¡pero usted depende de la configuración del servidor!fuente
server_name
directiva. Especialmente si noserver_name
se establece, también_SERVER["SERVER_NAME"]
estará vacío.HTTP_HOST
es 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_HOST
valor dewww.stackoverflow.com
.SERVER_NAME
proviene de laVirtualHost
definició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_HOST
siempre que los valores no válidos provenientes de un usuario malintencionado no puedan romper nada.fuente
UseCanonicalName on
Debe usar en httpd.conf para forzarSERVER_NAME
a 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_HOST
contiene el puerto, mientrasSERVER_NAME
que 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_HOST
no no contiene:443
cuando 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_HOST
lugar 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_NAME
generalmente es el nombre del VirtualHost, no el servidor en sí. Y en Apache, aSERVER_NAME
menudo se rellena con el mismo valor queHTTP_HOST
(ver la respuesta de BalusC).SERVER_NAME
aplica 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_NAME
es más confiable". Uso un servidor compartido y no tengo acceso a las directivas de host virtual. Por lo tanto, uso mod_rewrite en.htaccess
para asignar diferentes correos electrónicosHTTP_HOST
a diferentes directorios. En ese caso, esHTTP_HOST
que tiene sentido.La situación es similar si se usan hosts virtuales basados en nombres: la
ServerName
directiva 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_HOST
será 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_NAME
yHTTP_HOST
puede 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$_SERVER
superglobal 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 HTTPhost
encabezado . 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
).ServerValidator
comprueba 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 delhost
encabezado 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_POST
yINPUT_SERVER
en 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
host
encabezado 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 deServerName
en el httpd.conf , y, por extensión, el valor de$_SERVER('SERVER_NAME')
la$_SERVER
superglobal. Una vez más, estaría usandoINPUT_SERVER
las funciones de filtro de PHP, pero me entiendes.Tenga en cuenta que Apache usa con frecuencia
ServerName
en 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