$_SERVER['HTTP_HOST']和$_SERVER['SERVER_NAME']在PHP中的区别是什么?

什么时候你会考虑使用其中一种而不是另一种,为什么?


当前回答

$_SERVER['SERVER_NAME']基于您的web服务器配置。 $_SERVER['HTTP_HOST']是基于来自客户端的请求。

其他回答

看我想知道什么了。SERVER_NAME是服务器的主机名,而HTTP_HOST是客户端连接到的虚拟主机。

正如balusC所说,SERVER_NAME是不可靠的,可以在apache配置中更改,服务器的服务器名配置以及您和服务器之间的防火墙。

以下函数总是返回没有端口的真实主机(用户键入的主机),几乎是可靠的:

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

HTTP_HOST是客户端发送的目标主机。用户可以自由操作。向站点发送请求请求HTTP_HOST值www.stackoverflow.com是没有问题的。

SERVER_NAME来自服务器的VirtualHost定义,因此被认为更可靠。然而,它也可以在与您的web服务器设置相关的某些条件下从外部操纵:请看这个SO问题,处理这两种变体的安全方面。

你不应该依赖任何一个来保证安全。也就是说,用什么真的取决于你想做什么。如果你想确定你的脚本在哪个域上运行,只要来自恶意用户的无效值不能破坏任何东西,你就可以安全地使用HTTP_HOST。

正如我在回答中提到的,如果服务器运行在不是80的端口上(在开发/intranet机器上可能很常见),那么HTTP_HOST包含端口,而SERVER_NAME不包含端口。

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

(至少这是我在Apache基于端口的虚拟主机中注意到的)

注意在HTTPS上运行时HTTP_HOST不包含:443(除非您在非标准端口上运行,我没有测试过)。

正如其他人所指出的,这两者在使用IPv6时也有所不同:

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

我花了一段时间才理解人们所说的“SERVER_NAME更可靠”是什么意思。我使用共享服务器,不能访问虚拟主机指令。因此,我在.htaccess中使用mod_rewrite来将不同的HTTP_HOSTs映射到不同的目录。在这种情况下,HTTP_HOST是有意义的。

The situation is similar if one uses name-based virtual hosts: the ServerName directive within a virtual host simply says which hostname will be mapped to this virtual host. The bottom line is that, in both cases, the hostname provided by the client during the request (HTTP_HOST), must be matched with a name within the server, which is itself mapped to a directory. Whether the mapping is done with virtual host directives or with htaccess mod_rewrite rules is secondary here. In these cases, HTTP_HOST will be the same as SERVER_NAME. I am glad that Apache is configured that way.

但是,基于ip的虚拟主机的情况有所不同。在这种情况下,且仅在这种情况下,SERVER_NAME和HTTP_HOST可以是不同的,因为现在客户端通过IP而不是名称来选择服务器。确实,在某些特殊的构型中这很重要。

因此,从现在开始,我将使用SERVER_NAME,以防我的代码移植到这些特殊配置中。