server_name request_uri http_host example _server php apache server-variables

request_uri - ¿Cuál es la diferencia entre HTTP_HOST y SERVER_NAME en PHP?



http_host example (9)

Como balusC dijo que SERVER_NAME no es confiable y puede cambiarse en apache config, configuración de nombre de servidor del servidor y 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:

function getRealHost(){ list($realHost,)=explode('':'',$_SERVER[''HTTP_HOST'']); return $realHost; }

¿Cuándo consideraría usar uno sobre el otro y por qué?


Como mencioné en esta respuesta , si el servidor se ejecuta en un puerto distinto de 80 (como puede ser común en una máquina de desarrollo / intranet), HTTP_HOST contiene el puerto, mientras que SERVER_NAME no lo hace.

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

(Al menos eso es lo que he notado en los hosts virtuales basados ​​en puertos de Apache)

Tenga en cuenta que HTTP_HOST no contiene :443 cuando se ejecuta en HTTPS (a menos que se esté ejecutando en un puerto no estándar, que no he probado).

Como han señalado otros, los dos también difieren cuando se usa IPv6:

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


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.


El HTTP_HOST se obtiene del encabezado de solicitud HTTP y esto es lo que el cliente realmente usó como "host de destino" de la solicitud. El SERVER_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 de negocios 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ón tenga el SERVER_NAME configurado correctamente. Tomando Apache HTTPD como ejemplo, aquí hay un extracto de su documentación :

Si no se especifica ningún ServerName servidor, el servidor intenta deducir el nombre de host realizando una búsqueda inversa en la dirección IP. Si no se especifica ningún puerto en ServerName , entonces el servidor usará el puerto de la solicitud entrante. Para una confiabilidad y previsibilidad óptimas, debe especificar un nombre de host y un puerto explícitos utilizando la directiva ServerName .

Actualización : después de verificar la respuesta de Pekka en su pregunta que contiene un enlace a la respuesta de Bobince, PHP siempre devolverá el valor de SERVER_NAME para SERVER_NAME , que va en contra de mis propias experiencias de PHP 4.x + Apache HTTPD 1.2.x de un par de Hace 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 los dos valores, creé una aplicación de prueba Java utilizando URLConnection para modificar El encabezado de Host y las pruebas me enseñaron que este es el caso (incorrectamente).

Después de sospechar por primera vez de PHP e investigar algunos informes de errores de PHP relacionados con el tema, me enteré de que la raíz del problema se encuentra en el servidor web utilizado, que devolvió incorrectamente el encabezado del Host HTTP cuando se solicitó SERVER_NAME . Así que busqué en los informes de errores de Apache HTTPD usando varias palabras clave relacionadas con el tema y finalmente encontré un error relacionado . Este comportamiento fue introducido desde alrededor de Apache HTTPD 1.3. UseCanonicalName configurar la directiva UseCanonicalName en la entrada <VirtualHost> del ServerName en httpd.conf (¡también revise la advertencia en la parte inferior del UseCanonicalName !).

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

Esto funcionó para mí.

Resumido, SERVER_NAME es más confiable, ¡pero depende de la configuración del servidor!


Me tomó un tiempo entender lo que la gente quiere decir con '' SERVER_NAME es más confiable''. Utilizo un servidor compartido y no tengo acceso a directivas de host virtual. Por lo tanto, uso mod_rewrite en .htaccess para asignar diferentes HTTP_HOST a diferentes directorios. En ese caso, es HTTP_HOST que es significativo.

La situación es similar si uno usa hosts virtuales basados ​​en nombres: la directiva ServerName 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 a su vez se asigna a un directorio. Si la asignación se realiza con directivas de host virtual o con las reglas htaccess mod_rewrite es secundaria aquí. En estos casos, HTTP_HOST será el mismo que SERVER_NAME . Me alegro de 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 y HTTP_HOST pueden ser diferentes, porque ahora el cliente selecciona el servidor por IP, no por su nombre. De hecho, puede haber configuraciones especiales donde esto es importante.

Así que, a partir de ahora, SERVER_NAME , en caso de que mi código sea portado en estas configuraciones especiales.


Si desea consultar a través de un server.php o como quiera llamarlo con lo siguiente:

<?php phpinfo(INFO_VARIABLES); ?>

o

<?php header("Content-type: text/plain"); print_r($_SERVER); ?>

Luego acceda a él con todas las URL válidas para su sitio y revise la diferencia.


Suponiendo que uno tiene una configuración simple (CentOS 7, Apache 2.4.x, y PHP 5.6.20) y solo un sitio web (no asumiendo el alojamiento virtual) ...

En el sentido de PHP, $_SERVER[''SERVER_NAME''] es un elemento que PHP registra en el superglobal $_SERVER basado en su configuración de Apache ( **ServerName** directiva con UseCanonicalName On ) en httpd.conf (ya sea desde un host virtual incluido) archivo de configuración, lo que sea, etc ...). HTTP_HOST se deriva del encabezado de host HTTP. Trate esto como entrada del usuario. Filtrar y validar antes de usar.

Aquí hay un ejemplo de donde uso $_SERVER[''SERVER_NAME''] como base para una comparación. El siguiente método es de una clase secundaria concreta que hice llamada ServerValidator (hijo de Validator ). ServerValidator comprueba seis o siete elementos en $ _SERVER antes de usarlos.

Al determinar si la solicitud HTTP es POST, uso este método.

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

En el momento en que se llame a este método, todo el filtrado y la validación de los elementos $ _SERVER relevantes se habrían producido (y se habrían establecido las propiedades relevantes).

La línea ...

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

... comprueba que el $_SERVER[''HTTP_HOST''] (derivado en última instancia del encabezado HTTP del host solicitado) coincida con $_SERVER[''SERVER_NAME''] .

Ahora, estoy usando el lenguaje superglobal para explicar mi ejemplo, pero eso se debe a que algunas personas no están familiarizadas con INPUT_GET , INPUT_POST e INPUT_SERVER en lo que respecta a filter_input_array() .

La conclusión es que no manejo las solicitudes POST en mi servidor a menos que se cumplan las cuatro condiciones. Por lo tanto, en términos de solicitudes POST, el hecho de no proporcionar un encabezado de host HTTP (presencia probada anteriormente) deletrea la perdición de los navegadores HTTP 1.0 estrictos. Además, el host solicitado debe coincidir con el valor de ServerName en httpd.conf y, por extensión, el valor para $_SERVER(''SERVER_NAME'') en el $_SERVER superglobal. Una vez más, estaría usando INPUT_SERVER con las funciones de filtro de PHP, pero atrapa mi deriva.

Tenga en cuenta que Apache usa con frecuencia el nombre del ServerName en redirecciones estándar (como dejar la barra inclinada fuera de una URL: Ejemplo, http://www.foo.com/ convierte en http://www.foo.com/ ), incluso si está No se utiliza la reescritura de URL.

Utilizo $_SERVER[''SERVER_NAME''] como estándar, no $_SERVER[''HTTP_HOST''] . Hay un montón 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, solo porque ambos pueden ser establecidos no garantiza que serán iguales. La prueba es la mejor manera de saberlo con seguridad (teniendo en cuenta la versión de Apache y la versión de PHP).


Tenga en cuenta que si desea utilizar IPv6, probablemente desee utilizar HTTP_HOST lugar de SERVER_NAME . Si ingresa http://[::1]/ las variables de entorno serán las siguientes:

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

Esto significa que si hace un mod_rewrite por ejemplo, puede obtener un resultado desagradable. Ejemplo para una redirección 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}/

Esto se aplica SOLAMENTE si accede al servidor sin un nombre de host.


HTTP_HOST es el host de destino enviado por el cliente. Puede ser manipulado libremente por el usuario. No es un problema enviar una solicitud a su sitio solicitando un valor www..com de www..com .

SERVER_NAME proviene de la definición de VirtualHost del servidor y, por lo tanto, se considera más confiable. Sin embargo, también puede manipularse desde el exterior bajo ciertas condiciones relacionadas con la configuración de su servidor web: vea esto Esta pregunta de SO que trata sobre los aspectos de seguridad de ambas variaciones.

No debes confiar en ninguno de los dos para estar seguro. Dicho esto, lo que se debe usar realmente depende de lo que se quiera hacer. Si desea determinar en qué dominio se está ejecutando su script, puede usar HTTP_HOST forma segura siempre que los valores no válidos provenientes de un usuario malintencionado no puedan romper nada.