2011-06-18 20 views
30

我jQuery的jQuery的$.getJSON()函數返回一組簡短的JSON數據。jQuery.getJSON - 訪問控制 - 允許來源問題

我得到了一個URL上的JSON數據,如example.com。 我沒有意識到這一點,但當我訪問相同的網址時,無法加載JSON數據。我通過控制檯,發現XMLHttpRequest無法加載,因爲Access-Control-Allow-Origin

現在,我已經通讀了很多網站,只是說使用$.getJSON(),這將是工作,但顯然它沒有奏效。有什麼我應該改變在標題或功能?

非常感謝幫助。

+2

也許你可能想看看JSONP:http://en.wikipedia.org/wiki/JSONP。 – pimvdb

+0

另一種方法是使用代理(例如PHP curl)轉發您的請求和響應(如果可用)。 – Dan

回答

36

您可能很想使用JSON-P(請參閱下文)。首先快速解釋一下。

您提到的標題是從Cross Origin Resource Sharing標準。請注意,某些瀏覽器人們實際使用的是not supported,而在其他瀏覽器(微軟的感嘆號)中,它需要使用特殊對象(XDomainRequest)而不是jQuery使用的標準XMLHttpRequest。它還要求您更改服務器端資源以明確允許其他來源(www.xxxx.com)。

爲了讓你請求JSON數據,你基本上有三種選擇:

  1. 如果可能的話,你可以通過糾正你加載所以他們有文件的位置是最大兼容與您要加載的文檔的來源相同。 (我假設你必須通過Ajax加載它們,因此Same Origin Policy問題顯示出來。)

  2. 使用JSON-P,它不受SOP限制。 jQuery內置支持它的ajax調用(只需將dataType設置爲「jsonp」,jQuery將完成所有客戶端工作)。這需要服務器端的變化,但不是很大的變化;基本上無論你有什麼產生JSON響應,只是尋找一個名爲「回調」的查詢字符串參數,並將JSON封裝在可調用該函數的JavaScript代碼中。例如,如果你目前的JSON的反應是:

    {"weather": "Dreary start but soon brightening into a fine summer day."} 
    

    你的腳本將尋找「回調」查詢字符串參數(假設該參數的值是「jsop123」),幷包裝了JSON在語法爲JavaScript函數調用:

    jsonp123({"weather": "Dreary start but soon brightening into a fine summer day."}); 
    

    就是這樣。 JSON-P是非常兼容(因爲它通過JavaScript script標籤工作)。 JSON-P僅適用於GET,但不是POST(同樣因爲它通過script標籤工作)。

  3. 使用CORS(與引用的標題相關的機制)。在the specification linked above的詳細信息,但基本上:

    答:瀏覽器將使用OPTIONS HTTP動詞(方法)向您的服務器發送「預檢」消息。它將包含它將用GETPOST以及標題「Origin」,「訪問控制請求方法」(例如,GETPOST)和「Access-Control-Request-Headers」 (它想要發送的標題)。您的PHP根據這些信息決定請求是否正常,如果是,則響應「Access-Control-Allow-Origin」,「Access-Control-Allow-Methods」和「Access-Control-Allow-Methods」 Control-Allow-Headers「標題以及它將允許的值。您不會發送任何正文(頁面)與該響應。

    C.瀏覽器會查看您的回覆,看看是否允許向您發送實際的GETPOST。如果是這樣,它將再次發送該請求,並帶有「Origin」和各種「Access-Control-Request-xyz」標題。

    D.您的PHP檢查這些標頭再次以確保它們仍然可以,並且如果響應請求。

    -code(我沒有做太多PHP的,所以我並不想在這裏做PHP語法):

    // Find out what the request is asking for 
    corsOrigin = get_request_header("Origin") 
    corsMethod = get_request_header("Access-Control-Request-Method") 
    corsHeaders = get_request_header("Access-Control-Request-Headers") 
    if corsOrigin is null or "null" { 
        // Requests from a `file://` path seem to come through without an 
        // origin or with "null" (literally) as the origin. 
        // In my case, for testing, I wanted to allow those and so I output 
        // "*", but you may want to go another way. 
        corsOrigin = "*" 
    } 
    
    // Decide whether to accept that request with those headers 
    // If so: 
    
    // Respond with headers saying what's allowed (here we're just echoing what they 
    // asked for, except we may be using "*" [all] instead of the actual origin for 
    // the "Access-Control-Allow-Origin" one) 
    set_response_header("Access-Control-Allow-Origin", corsOrigin) 
    set_response_header("Access-Control-Allow-Methods", corsMethod) 
    set_response_header("Access-Control-Allow-Headers", corsHeaders) 
    if the HTTP request method is "OPTIONS" { 
        // Done, no body in response to OPTIONS 
        stop 
    } 
    // Process the GET or POST here; output the body of the response 
    

    再度強調,這是僞代碼。

+0

有沒有辦法利用jQuery來做到這一點?或者,是否有一個我可以設置的頭文件(通過PHP)可以讓它工作? – Mike

+0

@Mike:哪個「這個」?如果你的意思是JSON-P,是的,jQuery支持'ajax'調用;我已經在上面添加了一些細節。如果你的意思是CORS,那麼是的,這是你通過PHP設置的頭文件,以響應'OPTIONS'HTTP請求,並且再次響應'GET'或'POST';我也爲此添加了一些細節。但是如果有任何機會你可以移動這些文件使它們位於同一個原點,那麼這一切都是矯枉過正的。 –

+0

@ T.J.Crowder所以$ .getJSON不起作用?我們是否需要使用其他方法如ajax並設置標題? – Dinesh

66

很簡單,使用$.getJSON()功能,在您的網址只是包括

回調=?

作爲參數。這將把該調用轉換爲進行跨域調用所必需的JSONP。更多信息:http://api.jquery.com/jQuery.getJSON/

+18

這完全取決於服務器接受額外的回調參數,它在任何情況下都不可以。 – Simon

+7

這並不工作100%的時間,如果服務器沒有設置爲服務器jsonp然後它仍然返回json,其中你會得到一個錯誤。 – chadpeppers

+1

這對我有用,謝謝! – FrontENG