PHP中是否存在$ _SERVER ?

在整个互联网上,即使在Stack Overflow也包括在内,人们认为检查请求是否是AJAX的一个好方法是执行以下操作:

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

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

而当我试图做到以下几点:

 echo $_SERVER['HTTP_X_REQUESTED_WITH']; 

没有输出。

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

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

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

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

不要忘记,你可以很容易地用cURL来欺骗任何标题

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

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

这个头文件是从那里的所有AJAX库进行标准化的。

它不会被logging在php文档本身,而是在设置这个头的不同的AJAX库中。 通用库确实发送了这个头文件:jQuery,Mojo,Prototype,…

通常这些库将使用设置标题

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

以下是一个使用示例的快速函数:

 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'; } 
 echo $_SERVER['HTTP_X_REQUESTED_WITH']; 

你对这样的代码有什么期望? 假设您直接从浏览器运行它,而不是使用AJAX请求。 那么,怎样才能设置这个标题呢?

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

Firebug有一个,或者你可能想使用Fiddler HTTP代理或者LiveHTTPHeaders Mozilla插件。 我很无聊,但很容易上网。

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

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

您也可以责怪一些浏览器错误 – 看到这个问题及其解决scheme的Firefox

Firefox在Ajax请求redirect期间不保留自定义标头:ASP.NET MVC解决scheme

IE也有caching问题 ,这是比较严重的请求方法的检测。

您无论如何需要添加caching,以避免caching,所以为什么不使用另一个标志来指定ajax调用 – 或者更好地,你可以使用不同的URL,如http://ajax.mysite.com/endpoint/sevice?params

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

确保HTTP请求是否真正通过AJAX发送的最佳解决scheme是使用SESSION检查,在get参数中发送session_id,并在允许或不允许的情况下检查会话。

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

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

  1. 当我不在跨域的情况下,我可以使用HTTP_X_REQUESTED_WITH。

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

  3. 我的API期望从客户端明确,在less数情况下,数据types(JSON,HTML等)到GET或POST var。 例如,我检查$ _REQUEST ['ajax']是否为空或等于期望值。