PHP中是否存在$ _SERVER ['HTTP_X_REQUESTED_WITH']?

时间:2010-04-05 15:38:39

标签: php ajax http-headers

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

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

但是,我在official PHP documentation

中看不到$_SERVER['HTTP_X_REQUESTED_WITH']

当我尝试执行以下操作时:

echo $_SERVER['HTTP_X_REQUESTED_WITH'];

没有输出任何东西。

我做错了吗?因为如果可以的话,我真的希望能够使用$_SERVER['HTTP_X_REQUESTED_WITH']

11 个答案:

答案 0 :(得分:59)

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

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

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

答案 1 :(得分:27)

不要忘记你可以轻易地用cURL欺骗任何标题

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

答案 2 :(得分:17)

$_SERVER开头的

HTTP_密钥是从HTTP请求标头生成的。在这种情况下,X-Requested-With标题。

答案 3 :(得分:11)

此标头是所有AJAX库中的标准化进程。

它不会在php文档中记录,而是在设置此标头的不同AJAX库中记录。公共库确实发送了这个头:jQuery,Mojo,Prototype,......

通常这些库将使用

设置标题
xhrobj.setRequestHeader("X-Requested-With", "XMLHttpRequest");

答案 4 :(得分:4)

以下是一个使用示例的快速功能:

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';
}

答案 5 :(得分:3)

echo $_SERVER['HTTP_X_REQUESTED_WITH'];

您对此类代码的期望是什么?假设您直接从浏览器运行它,而不是使用AJAX请求。那么,为什么要设置这个标题?

生命,宇宙和万物的终极问题的答案 - HTTP嗅探器!给自己一个,忘记打印$ _SERVER变量。

Firebug有一个,或者您可能想要使用Fiddler HTTP代理或LiveHTTPHeaders Mozilla插件。我很无聊,但很容易用Google搜索链接。

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

请注意,使用XHR无法阻止任何“直接访问”,因为对服务器的每个HTTP请求都已“直接”。

答案 6 :(得分:1)

您还可以归咎于某些浏览器错误 - 请参阅此问题及其Firefox解决方案

Firefox does not preserve custom headers during Ajax request redirect: an ASP.NET MVC solution

IE也有caching issue,这比检测请求方法更严重。

你无论如何都需要添加缓存破坏程序以避免缓存,所以为什么不使用另一个标志来指定ajax调用 - 或者更好的是你可以使用不同的URL,如http://ajax.mysite.com/endpoint/sevice?params

答案 7 :(得分:1)

$headers = apache_request_headers();
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest');

答案 8 :(得分:0)

确保通过AJAX真正发送HTTP请求的最佳解决方案是使用SESSION检查,您在get参数中发送session_id,如果允许或不允许,请检查此会话!

答案 9 :(得分:0)

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

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

  1. 当我不在跨域上下文中时,我可以使用HTTP_X_REQUESTED_WITH。

  2. 而不是检查" X-requested-with",我正在检查$ _SERVER [' HTTP_ORIGIN'](从AJAX请求发送)意图处理跨域权限。大多数时候,我检查请求是否是AJAX请求的主要原因,特别是因为跨域权限,使用此PHP代码:header(' Access-Control-Allow-Origin:& #39; $ _ SERVER [' HTTP_ORIGIN']); //如果这是" HTTP_ORIGIN"在我的白名单中

  3. 我的API期望客户端在极少数情况下将数据类型(JSON,HTML等)显式转换为GET或POST var。例如,我检查$ _REQUEST [' ajax']是否为空或等于预期值。

答案 10 :(得分:0)

您必须在ajax请求对象中进行专门设置​​(也就是说,如果您未使用jQuery之类的框架),而是使用核心Javascript;像这样:

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

xhr是您的请求对象。

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

$_SERVER['HTTP_X_REQUESTED_WITH']

否则$ _SERVER ['HTTP_X_REQUESTED_WITH']始终为空。

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