PHP:检查$_SERVER ['HTTP_REFERER']相等的最佳方法是什么?

5

我有一个 PHP 脚本,用于检查 HTTP Referer。

if ($_SERVER['HTTP_REFERER'] == 'http://www.example.com/') {...}

然而,这似乎本质上是不安全的...因为如果用户前往 'http://example.com/''http://www.ExaMple.com'(两者都不符合相等性测试),会发生什么情况。

问题:有什么更好的相等性测试方法来确保HTTP Referer来自 'example.com'


你是用它来进行防御吗?它如何帮助你? - Your Common Sense
这只是第一道防线(特别是考虑到我知道引用者可以被欺骗)。它并没有保护任何安全内容,但同时,我也不希望人们直接调用我的 Web 服务来滥用它。它更多的是为了让人们半诚实。 - Hank
用户可以使用篡改数据来控制http_referer。然而,引用者无法被“伪造”以在CSRF攻击中使用。 - rook
5个回答

3

parse_url()加上一些字符串操作可以实现你想要的功能。试试这个:

$url = parse_url($_SERVER['HTTP_REFERER']);
//take the last two 'dot segments' of the host
$hostOnly = implode('.',array_slice(explode('.',$url['host']),-2));
if (strtolower($hostOnly) == 'example.com') {
    //stuff
}

请注意,parse_url()可能无法解析格式不正确的URL,因此您可能需要添加一些错误检查以确保安全。HTTP_REFERER很容易被填充垃圾信息。

1

必要的回应:HTTP_REFERER 可以被欺骗,所以无法百分之百确定任何人来自特定的网站。

但是如果您确实想依赖它,您可以使用正则表达式在 HTTP_REFERER 中查找 "example.com"。stristr() 也可以工作,并且可能会推荐使用,因为它比正则表达式更快。它也不区分大小写,所以它将匹配 "ExaMple.com" 和 'example.com"。


这仍然是一个不错的第一道防线,但无论如何感谢您提到它。 - Hank
1
但是 stristr 不会匹配 "notmyExample.com",这是不可取的吗? - Hank

1

希望您不要检查它是否有任何重要信息。

您可以使用parse_url()函数获取主机名部分,并检查HTTP_REFERER是否实际包含网址。
您也可以仅从主机名中截取www.
字符大小写不重要,因为它始终是小写的。

或者使用正则表达式。


0
if (strtolower($_SERVER['HTTP_REFERER']) == 'http://www.example.com/') {...}

怎么样...

$parts = explode('/',$_SERVER['HTTP_REFERER']);
if (in_array('example.com',$parts) || in_array('www.example.com',$parts)) {...}

1
不确定这会一直有效,因为它假设1)有一个尾随斜杠,2)用户访问的是http://example.com而不是直接访问“www.”。 - Hank
URL 应该始终进行规范化处理,即将次要域名重定向到主要域名(当使用多个域名时)。http://zh.wikipedia.org/wiki/%E8%A7%84%E8%8C%83%E5%8C%96 - jholster

0
使用正则表达式,这将变成:
if(preg_match("%(http://)?(www\.)?example\.com(/)?%i",$_SERVER['HTTP_REFERER'])) { ... }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接