PHP 中是否存在 $_ SERVER [‘ HTTP_X_REQUESTED_WAS’] ?

在整个互联网上,甚至在 Stack Overflow 这里,人们都说检查一个请求是否是 AJAX 的一个好方法是执行以下操作:

if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' ) {...}

但是,我没有看到 $_SERVER['HTTP_X_REQUESTED_WITH']PHP 官方文档

当我尝试做以下事情时:

echo $_SERVER['HTTP_X_REQUESTED_WITH'];

没有输出。

我做错了什么吗? 因为我真的希望能够使用 $_SERVER['HTTP_X_REQUESTED_WITH'],如果它是可用的。

77190 次浏览

HTTP_开头的 $_SERVER键是从 HTTP 请求标头生成的。

$_SERVER中的变量实际上不是 PHP 的一部分,这就是为什么在 PHP 文档中找不到它们的原因。它们是由网络服务器准备的,网络服务器将它们传递给脚本语言。

据我所知,X-Requested-With是由大多数主要框架的 Ajax 函数发送的,但不是全部(例如,Dojo 仅在两年前添加了它: # 5801)。因此,考虑到@bobince 的评论,可以肯定地说,它通常不是一个100% 可靠的方法来确定一个请求是否是 AJAX 请求。

唯一100% 安全的方法是发送一个预定义的标志(例如 GET 变量)和请求,并让接收页面检查标志是否存在。

这个头是所有 AJAX 库正在进行的标准化工作。

它本身不会在 php 文档中进行记录,而是在设置此头部的不同 AJAX 库中进行记录。公共库发送这个头: jQuery、 Mojo、 Prototype、 ..。

通常,这些库将使用

xhrobj.setRequestHeader("X-Requested-With", "XMLHttpRequest");
echo $_SERVER['HTTP_X_REQUESTED_WITH'];

你以为这样的密码是什么?假设您直接从浏览器运行它,而不是使用 AJAX 请求。那么,为什么可以设置这个头部?

生命、宇宙和一切终极问题的答案—— HTTP 嗅探器!给自己找一个,然后忘记打印 $_ SERVER 变量。

Firebug 有一个,或者您可能想使用 Fiddler HTTP 代理或 LiveHTTPHeaders Mozilla 插件。我厌倦了建立链接,但它很容易谷歌。

因此,使用 HTTP 嗅探器,您可以确定任何 HTTP 报头。

请注意,您不能通过使用 XHR 来阻止任何“直接访问”,因为对服务器的每个 HTTP 请求都已经是“直接”的。

不要忘记,您可以像这样轻松地使用 cURL 欺骗任何头文件

curl_setopt($ch,CURLOPT_HTTPHEADER,array("X-Requested-With : XMLHttpRequest"));

你也可以归咎于一些浏览器错误——看看这个问题及其对 Firefox 的解决方案

Firefox 在 Ajax 请求重定向期间不保留自定义头: ASP.NET MVC 解决方案

IE 也有比请求检测方法更严重的 缓存问题

无论如何,您需要添加缓存终结器来避免缓存,因此为什么不使用另一个标志来指定 ajax 调用——或者更好的方法是使用不同的 URL,如 http://ajax.mysite.com/endpoint/sevice?params

确保 HTTP 请求是否真正通过 AJAX 发送的最佳解决方案是使用 SESSION 检查,在 get 参数中发送 SESSION _ id,然后检查这个会话是否允许!

下面是一个带有示例用法的快速函数:

function isXmlHttpRequest()
{
$header = isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? $_SERVER['HTTP_X_REQUESTED_WITH'] : null;
return ($header === 'XMLHttpRequest');
}


// example - checking our active call
if(!isXmlHttpRequest())
{
echo 'Not an ajax request';
}
else
{
echo 'is an ajax request';
}
$headers = apache_request_headers();
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest');

我同意佩卡。在前端和后端之间没有可靠的本机方法可以自动检测客户端是否真的在使用 AJAX 调用端点。

对于我自己的使用,我有几个主要的方法来检查客户端是否请求我的端点之一:

  1. 当我不在跨域上下文中时,我可以使用 HTTP _ X _ REQUESTED _ WAS。

  2. 不是检查“ X-request-with”,而是检查 $_ SERVER [‘ HTTP _ ORIGIN’](从 AJAX 请求发送) ,以处理跨域权限。大多数时候,我检查一个请求是否是 AJAX 请求的主要原因,尤其是因为跨域权限,使用这个 PHP 代码: header (“ Access-Control-allow-Origin:”)。$_ SERVER [‘ HTTP _ ORIGIN’] ;//如果这个“ HTTP _ ORIGIN”在我的白名单中

  3. 我的 API 期望从客户机显式,在少数情况下,数据类型(JSON,HTML 等)到一个 GET 或 POST 变量。例如,我检查 $_ REQUEST [‘ ajax’]是否为空或等于预期值。

您必须在 ajax 请求对象中专门设置它(即如果您不使用 jQuery 这样的框架) ,但是必须使用核心 Javascript; 如下所示:

xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");

其中 xhr是请求对象。

然后,PHP将接收并设置它在全局变量 $_SERVER中,如下所示:

$_SERVER['HTTP_X_REQUESTED_WITH']

否则 $_ SERVER [‘ HTTP _ X _ REQUESTED _ WITH’]将始终为 null。

注意 : 在您的 javascript 中,请确保在请求打开后设置头部。我的意思是在 xhr.open()方法之后。