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

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


当前回答

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

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

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

其他回答

如果你想检查server.php或其他什么,你想用下面的方法调用它:

<?php
    phpinfo(INFO_VARIABLES);
?>

or

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

    print_r($_SERVER);
?>

然后使用您站点的所有有效url访问它,并检查差异。

看我想知道什么了。SERVER_NAME是服务器的主机名,而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'

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

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

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

请注意,如果你想使用IPv6,你可能想使用HTTP_HOST而不是SERVER_NAME。如果输入http://[::1]/,则环境变量如下:

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

这意味着,如果你做一个mod_rewrite,你可能会得到一个糟糕的结果。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}/

这只适用于在没有主机名的情况下访问服务器。