2010-04-05 65 views
61

所有在互聯網上,甚至包括在這裏堆棧溢出,人指出,檢查的好方法,如果請求是AJAX與否是做到以下幾點:

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

不過,我沒有看到$_SERVER['HTTP_X_REQUESTED_WITH']official PHP documentation

,當我嘗試做以下:

echo $_SERVER['HTTP_X_REQUESTED_WITH']; 

沒有被輸出。

我做錯了什麼?因爲如果可用,我真的很希望能夠使用$_SERVER['HTTP_X_REQUESTED_WITH']

回答

17

$_SERVERHTTP_開始的密鑰是從HTTP請求頭生成的。在這種情況下,X-Requested-With標題。

+0

那麼所有的瀏覽器都設置了這個頭文件嗎?另外,如果這是一個AJAX調用,這個頭文件如何設置? – Hank 2010-04-05 15:42:23

+0

XHR可以在請求中發送任意標題。 – 2010-04-05 15:43:49

+0

@Hank AJAX調用有什麼問題?你認爲它不使用HTTP請求?哪一個呢? – 2010-04-05 15:45:16

56

$_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-04-05 15:45:14

+1

@bobince是否真的有可能是防火牆會混亂呢?我正在構建一個Web應用程序,它將主要用於一個位置,偶爾還可以遠程使用。能夠從請求類型抽象出來真的很好,因此我的控制器可以返回整個頁面或html代碼片段,具體取決於它是否是ajax請求... – rgvcorley 2012-06-12 21:15:21

+0

@rgvcorley:典型的現代代理不會任意刪除標題(移動網絡有一些令人討厭的破碎的標題)。但是,如果你有任何東西,除了'nocache'響應,'Vary'問題*將會和你一起搞砸。這是不值得的麻煩,因爲標題漂亮的小改進;去一個簡單的參數。 – bobince 2012-06-13 22:53:54

11

這個頭文件是所有AJAX庫的標準化進程。

它不會被記錄在php文檔本身,而是在設置此標頭的不同AJAX庫中。公共庫不發送這個頭:jQuery的,魔,原型,...

通常這些庫將設置使用

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

你從這樣的代碼想到什麼了頭?假設您直接從瀏覽器運行它,而不是使用AJAX請求。那麼,如何設置這個標題?

那麼對生命,宇宙和一切的終極問題的答案 - 一個HTTP嗅探器!讓自己一個人忘記打印$ _SERVER變量。

Firebug有一個,或者您可能想使用Fiddler HTTP代理或LiveHTTPHeaders Mozilla插件。我很無聊,但很容易上網。

因此,通過HTTP嗅探器,您可以確定任何HTTP頭。

請注意,您無法通過使用XHR阻止任何「直接訪問」,因爲對服務器的每個HTTP請求都已經是「直接訪問」。

+0

從瀏覽器和XHR,都沒有它輸出 – Hank 2010-04-05 15:51:14

+0

你怎麼知道XHR?你有沒有編碼答案? – 2010-04-05 15:57:00

27

不要忘記,你可以很容易地欺騙任何標頭,捲曲,像這樣

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

爲什麼你在這裏使用數組而不是字符串? – nssmart 2016-10-14 13:20:45

0

最好的解決方案,如果一個HTTP確保請求是通過AJAX真正發送使用SESSION檢查,您發送session_id在一個get參數,你檢查這個會話,如果它是允許的或不!

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'; 
} 
1
$headers = apache_request_headers(); 
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest'); 
+1

這似乎沒有解決實際問題。 – Kenster 2014-06-25 14:21:30

0

我同意佩卡。在前端和後端之間沒有可靠的本地方法,可以自動檢測客戶端是否真的使用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期望從客戶端明確,在少數情況下,數據類型(JSON,HTML等)到GET或POST var。例如,我檢查$ _REQUEST ['ajax']是否爲空或等於預期值。

相關問題