您何时会考虑使用其中一个,为什么?PHP中的HTTP_HOST和SERVER_NAME有什么区别?
回答
HTTP_HOST
从HTTP request header获得,这是客户端实际用作请求的“目标主机”的内容。 SERVER_NAME
在服务器配置中定义。使用哪一个取决于你需要的东西。然而,您现在应该意识到,这是一个客户端控制的值,因此可能不适用于业务逻辑,另一个是服务器控制的值更可靠。但是,您需要确保相关的网络服务器正确配置了SERVER_NAME
。以Apache的HTTPD为例,这里是从its documentation的摘录:
如果没有指定
ServerName
,那么服务器会尝试通过对IP地址进行反向查询来推断主机名。如果ServerName
中没有指定端口,则服务器将使用传入请求中的端口。为了获得最佳的可靠性和可预测性,您应该使用ServerName
指令指定明确的主机名和端口。
更新:检查the answer of Pekka on your question其中包含一个链接到bobince's answer后PHP会总是返回HTTP_HOST
的价值SERVER_NAME
,这违背了我自己的PHP 4.x版+ apache httpd的1.2.x的经验从几年前开始,我在Windows XP(Apache HTTPD 2.2.1,PHP 5.2.8)中使用了当前XAMPP环境中的一些灰尘,启动它,创建了一个打印这两个值的PHP页面,创建了一个Java测试应用程序使用URLConnection
修改Host
标题,测试告诉我这确实(不正确)。
第一怀疑PHP和挖掘一些PHP bug reports就这一课题后,我才知道,问题的根源是在使用Web服务器,它错误地返回的HTTP标头Host
时请求SERVER_NAME
。因此,我使用various keywords关于该主题挖掘了Apache HTTPD bug reports,并且我终于找到related bug。此行为是自Apache HTTPD 1.3开始引入的。您需要将UseCanonicalName
指令设置为on
,<VirtualHost>
输入ServerName
,httpd.conf
(同时检查the document底部的警告!)。
<VirtualHost *>
ServerName example.com
UseCanonicalName on
</VirtualHost>
这对我有效。
总结出来,SERVER_NAME
更可靠,但是你在上依赖在服务器上配置!
好的,这解决了我的问题,这与OP无关,但相关。使用浏览器可以提供的任何东西,我非常关心安全问题。这个答案是一个巨大的帮助。感谢您花时间把它放在一起。 – Yitzhak 2013-03-05 05:08:44
为什么你说HTTP_HOST不可靠?是的,它是由用户提供的,但如果用户给出一些虚假的值,你的服务器配置会自动返回503,你的PHP脚本甚至不会运行! – Pacerier 2013-07-14 15:01:49
@Prier:在写这个答案时,它没有。答案中提到了版本。我不再跟踪PHP了,所以我不能说它是否确实在更新的版本中发生了变化。 – BalusC 2013-07-14 15:03:02
取决于我想知道的。 SERVER_NAME是服务器的主机名,而HTTP_HOST是客户端连接到的虚拟主机。
获得的值不完全正确的Rowland,SERVER_NAME通常是VirtualHost的名称,而不是服务器本身。而在Apache中,'SERVER_NAME'通常被填入与'HTTP_HOST'相同的值(参见BalusC的回答)。 – 2013-08-20 00:24:59
@Simon,因为大多数主机现在都是VirtualHost,你认为“服务器本身”的名称是什么意思? – Pacerier 2015-03-05 23:23:24
如果您正在一个网站上运行虚拟专用服务器(VPS),则不需要假定“SERVER_NAME”适用于虚拟主机。但是,仍然可以为一个站点使用虚拟主机设置。许多人使用共享主机,所以我明白你的观点。 – 2017-03-09 05:38:52
HTTP_HOST
是客户端发送的目标主机。它可以由用户自由操纵。将请求发送到您的网站要求HTTP_HOST
的值为www.stackoverflow.com
是没有问题的。
SERVER_NAME
来自服务器的VirtualHost
定义,因此被认为更可靠。但是,它也可以在与您的Web服务器设置相关的特定条件下从外部操作:请参阅此处理这两个变体的安全方面的This SO question。
你不应该依赖要么是安全的。也就是说,使用什么取决于你想要做什么。如果要确定脚本运行在哪个域,只要来自恶意用户的无效值不能破坏任何内容,就可以安全地使用HTTP_HOST
。
是的,但是一个请求www.stackoverflow.com的HTTP_HOST值的请求会被大多数HTTP服务器拒绝,所以PHP脚本甚至不会看到请求! – Pacerier 2013-07-14 15:04:40
@Pacerier true,但并不总是如果服务器没有正确配置。 – 2013-07-14 15:18:39
正如在BalusC的文章中提到的,当您通过IP访问Apache虚拟主机时,*这两个变量都包含IP(默认情况下),而不是实际的服务器名称。您必须在httpd.conf中使用'UseCanonicalName on'来强制'SERVER_NAME'成为实际的服务器名称。 – 2013-08-20 00:17:27
,如果你想通过server.php或者你想叫它什么都检查以下内容:
<?php
phpinfo(INFO_VARIABLES);
?>
或
<?php
header("Content-type: text/plain");
print_r($_SERVER);
?>
然后用所有有效网址访问您的网站,并检查出差异。
我花了一段时间来理解人的意思“SERVER_NAME
更可靠”。我使用共享服务器,并且无法访问虚拟主机指令。因此,我使用.htaccess
中的mod_rewrite将不同的HTTP_HOST
映射到不同的目录。在这种情况下,这是有意义的HTTP_HOST
。
如果使用基于名称的虚拟主机,情况类似:虚拟主机中的ServerName
指令只是说明将哪个主机名映射到此虚拟主机。底线是,在这两种情况下,客户端在请求期间(HTTP_HOST
)提供的主机名必须与服务器中的名称相匹配,该名称本身映射到目录。映射是否通过虚拟主机指令完成,或者使用htaccess mod_rewrite规则在这里是次要的。在这些情况下,HTTP_HOST
将与SERVER_NAME
相同。我很高兴Apache可以这样配置。
不过,这种情况是与基于IP的虚拟主机不同。在这种情况下,只有在这种情况下,SERVER_NAME
和HTTP_HOST
可以不同,因为现在客户端通过IP选择服务器,而不是通过名称。事实上,这可能是特殊的配置,这很重要。
所以,从现在开始,我将使用SERVER_NAME
,以防万一我的代码是在这些特殊的配置移植。
请注意,如果你要使用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}/
仅当您访问没有主机名的服务器时才适用。
正如我在this answer提到的,如果服务器80以外的端口上运行(如可能是一个发展/内联网的计算机上常见的),那么HTTP_HOST
包含端口,而SERVER_NAME
没有。
$_SERVER['HTTP_HOST'] == 'localhost:8080'
$_SERVER['SERVER_NAME'] == 'localhost'
(至少这是我在Apache的基于端口的virtualhosts已经注意到)
注意HTTP_HOST
不不上HTTPS运行时,包含:443
(除非你在非运行标准端口,我没有测试过)。
正如其他人指出,这两个使用IPv6时也各不相同:
$_SERVER['HTTP_HOST'] == '[::1]'
$_SERVER['SERVER_NAME'] == '::1'
他们什么时候能解决这个阴险的行为? – Pacerier 2015-03-05 23:19:16
正如balusC说SERVER_NAME是不可靠的,并且可以在Apache的配置改变,服务器和防火墙的服务器名称的配置,可以是间你和服务器。
下面的函数总是返回真正的主机(用户输入的主机)没有端口,它几乎是可靠的:
function getRealHost(){
list($realHost,)=explode(':',$_SERVER['HTTP_HOST']);
return $realHost;
}
假设一个有一个简单的设置(CentOS的7,阿帕奇2.4.x的,和PHP 5.6.20)只有一个网站(不假设虚拟主机)...
在PHP的意义,$_SERVER['SERVER_NAME']
是一个元素PHP登记在$_SERVER
超全局基于在httpd.conf Apache配置(**ServerName**
指令与UseCanonicalName On
)(无论是从包含的虚拟主机配置文件中,无论如何, tc ...)。 HTTP_HOST源自HTTP host
标题。将此视为用户输入。使用前进行过滤和验证。
这里是我使用$_SERVER['SERVER_NAME']
作为比较基础的示例。以下方法来自具体的儿童课程,名称为ServerValidator
(Validator
的孩子)。在使用它们之前,ServerValidator
会检查$ _SERVER中的六个或七个元素。
在确定HTTP请求是否为POST时,我使用这种方法。
public function isPOST()
{
return (($this->requestMethod === 'POST') && // Ignore
$this->hasTokenTimeLeft() && // Ignore
$this->hasSameGETandPOSTIdentities() && // Ingore
($this->httpHost === filter_input(INPUT_SERVER, 'SERVER_NAME')));
}
的时候此方法被调用时,所有的过滤和相关的$ _SERVER元素的验证会发生(以及相关的属性设置)。
线...
($this->httpHost === filter_input(INPUT_SERVER, 'SERVER_NAME')
...检查该$_SERVER['HTTP_HOST']
值(最终从所请求的host
HTTP头衍生)匹配$_SERVER['SERVER_NAME']
。现在
,我使用超全局发言,解释我的例子,但这只是因为有些人不熟悉INPUT_GET
,INPUT_POST
和INPUT_SERVER
的问候filter_input_array()
。
底线是,我不处理我的服务器上的POST请求,除非全部满足四个条件。因此,就POST请求而言,对于严格的HTTP 1.0浏览器,未能提供HTTP头(在先测试存在)的拼写厄运。此外,该请求的主机必须将值在httpd.conf中ServerName
通过extention匹配,并且,在$_SERVER
超全局为$_SERVER('SERVER_NAME')
值。再次,我将使用INPUT_SERVER
与PHP的过滤功能,但你赶上我的漂移。
请阿帕奇经常标准使用ServerName
头脑重定向(如离开尾削减掉一个URL:例如,http://www.foo.com成为http://www.foo.com/),即使你不使用URL重写。
我用$_SERVER['SERVER_NAME']
作为标准,而不是$_SERVER['HTTP_HOST']
。这个问题上有很多来回。 $_SERVER['HTTP_HOST']
可能是空的,所以这不应该是创建代码约定的基础,比如我上面的公共方法。但是,仅仅因为两者都可能被设定并不能保证它们是平等的。测试是确切知道的最好方法(记住Apache版本和PHP版本)。
- 1. PHP中的 - >和::有什么区别?
- 2. PHP:$ _ SERVER变量:$ _ SERVER [ 'HTTP_HOST'] VS $ _ SERVER [ 'SERVER_NAME']
- 3. PHP中。=和+ =有什么区别?
- 4. PHP中sys_temp_dir和upload_tmp_dir有什么区别?
- 5. 在PHP中!==和!=有什么区别?
- 6. PHP中'isset()'和'!empty()'有什么区别?
- 7. php cli和php cgi有什么区别?
- 8. php 4和php 5有什么区别?
- 9. 有什么区别`和$(Bash中有什么区别?
- 10. PHP和Java有什么区别?
- 11. <?有什么区别?和<?php
- 12. JSP,PHP,HTML5和JavaScript有什么区别?
- 13. Php:|有什么区别?和||运营商
- 14. PHP header和Javascript window.location有什么区别?
- 15. phpinfo();有什么区别?和php -i?
- 16. javascript和PHP cookies有什么区别?
- 17. 有什么区别? :和||
- 18. &&和||有什么区别?
- 19. “/”和“/ *”有什么区别?
- 20. 有什么区别:。!和:r!?
- 21. ==和===有什么区别?
- 22. Appender和〜有什么区别?
- 23. $ @和$ *有什么区别?
- 24. is和=有什么区别?
- 25. #.00和#。##有什么区别?
- 26. `==`和`is`有什么区别?
- 27. '=='和'==='有什么区别?
- 28. /和/#/有什么区别?
- 29. | 0和~~有什么区别?
- 30. `&`和`ref`有什么区别?
“我通常会使用HTTP_HOST,以便用户保持他们开始使用的确切主机名。例如,如果我在.com和.org域中拥有相同的站点,我不想从.org到.com,特别是如果他们可能在.org上登录令牌,他们会丢失,如果发送到其他域。“ - 这和一些其他有趣的点从http://stackoverflow.com/questions/1459739/php-serverhttp-host-vs-serverserver-name-am-i-understanding-the-ma/1461430#1461430 – Yarin 2011-10-31 21:51:42
@Yarin,唐不要忘记[白名单 - 验证'HTTP_HOST'的结果](http://stackoverflow.com/a/28889208/632951)。否则,攻击者可以在HTTP的“Host:”请求中输入任何***值,并让服务器接受它。 – Pacerier 2015-03-05 22:53:29
初学者:这个问题是指通常通过'$ _SERVER ['HTTP_HOST']'或$ _SERVER ['SERVER_NAME']' – 2017-03-24 21:31:33