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


68

人们甚至在Stack Overflow的整个Internet上都指出,检查请求是否为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']它(如果有)。

Answers:


62

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

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

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


4
我也不认为这是一种可靠的方法。防火墙/代理工具可能对此感到不满意,并且如果您没有Vary: X-Requested-With在响应中结合使用此标头,则可能将错误的响应返回给代理用户……这反过来又加剧了IE中的缓存。很多人都会使用X-Requested-With,但是我认为这是一个糟糕的主意。最好在查询参数中传递一个标志,以表示您想要XMLHttp样式(或JSON)响应。
bobince 2010年

1
@bobince防火墙真的很可能会混乱吗?我正在构建一个Web应用程序,该应用程序将主要在一个位置使用,偶尔在远程使用。能够从请求类型中抽象出来真是太好了,这样我的控制器就可以返回整个页面或html代码段,具体取决于它是否是ajax请求...
rgvcorley 2012年

@rgvcorley:典型的现代代理不会任意删除标头(尽管移动网络使用了一些讨厌的,破损的破损标头)。但是,如果您除了回应之外,什么都Vary困扰您。这不值得麻烦,因为标题的漂亮度只有很小的提高。用一个简单的参数。nocache
bobince 2012年

感谢您的答复-是的,您是对的。我猜想对于GET变量所做的一点点额外工作,您就会知道它可以正常工作,从而使您受益匪浅!
rgvcorley12年

4
Dojo不是框架!这是一个图书馆。jQuery也是一个。不幸的是,“框架”一词演变成了一个流行词,经常被不正确地使用。
Sk8erPeter13年

27

不要忘记,您可以轻松地使用cURL欺骗任何标头,如下所示

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

为什么在这里使用数组而不是字符串?
nssmart

18

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


那么所有浏览器都设置了此标头吗?另外,如果是AJAX调用,则如何设置此标头?
汉克

XHR可以在请求中发送任意标头。
伊格纳西奥·巴斯克斯

@Hank AJAX调用怎么了?您认为它使用的不是HTTP请求吗?那是哪一个
您的常识

1
我试图阻止人们直接访问我的Web服务,但允许XHR
Hank 2010年

9
@Hank将XHR与“正常”请求区分开来是绝对安全的,从根本上讲是无用的,因为每个人都可以毫无问题地模拟XHRequest。您需要使用可靠的身份验证措施(或已经为主应用程序准备的任何其他措施)保护Ajax脚本。
Pekka 2010年

16

该头文件是所有AJAX库中正在进行的标准化。

不会在php文档本身中进行记录,而是在设置此标头的其他AJAX库中进行记录。通用库确实发送了此标头:jQuery,Mojo,Prototype等。

通常这些库会使用

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

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

这根本无法回答问题。OP正在询问的是这样的代码片段。他/她想知道它为什么起作用,即它$_SERVER['HTTP_X_REQUESTED_WITH']来自何处,在何处设置,以及是否/为什么我们可以真正依靠它。
osullic

3
echo $_SERVER['HTTP_X_REQUESTED_WITH'];

您希望从这样的代码中得到什么?假设您是直接从浏览器运行它,而不是使用AJAX请求。那么,如何设置此标头呢?

那么,对生命,宇宙和一切终极问题的答案-一个HTTP嗅探器!让自己一个,而忘记打印$ _SERVER变量。

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

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

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


从浏览器和XHR均未输出任何内容
Hank 2010年


0

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


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

2
这似乎没有解决实际问题。
Kenster 2014年

0

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

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

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

  2. 我正在检查打算处理跨域权限的$ _SERVER ['HTTP_ORIGIN'](从AJAX请求发送),而不是选择“ X-with-with”。大多数时候,我检查请求是否为AJAX请求的主要原因,尤其是由于跨域权限,使用此PHP代码:header('Access-Control-Allow-Origin:'。$ _ SERVER [' HTTP_ORIGIN']);//如果此“ HTTP_ORIGIN”在我的白名单中

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


0

您必须在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()方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.