參考資料:

 

JSONP 

維基百科,自由的百科全書

JSONPJSON with Padding)是資料格式 JSON 的一種「使用模式」,可以讓網頁從別的網域要資料。另一個解決這個問題的新方法是跨來源資源共享

由於同源策略,一般來說位於 server1.example.com 的網頁無法與不是 server1.example.com 的伺服器溝通,而HTML 的 <script> 元素是一個例外。利用 <script> 元素的這個開放策略,網頁可以得到從其他來源動態產生的 JSON 資料,而這種使用模式就是所謂的 JSONP。用 JSONP 抓到的資料並不是 JSON,而是任意的 JavaScript,用 JavaScript 直譯器執行而不是用 JSON 解析器解析。

原理

為了理解這種模式的原理,先想像有一個回傳 JSON 文件的 URL,而 JavaScript 程式可以用 XMLHttpRequest 跟這個 URL 要資料。假設我們的 URL 是 http://server2.example.com/RetrieveUser?UserId=xxx 。假設小明的 UserId 是 1823,且當瀏覽器透過 URL 傳小明的 UserId,也就是抓取 http://server2.example.com/RetrieveUser?UserId=1823,得到:

   {"Name": "小明", "Id" : 1823, "Rank": 7}

這個 JSON 資料可能是依據傳過去 URL 的查詢參數動態產生的。


這個時候,把 <script> 元素的 src 屬性設成一個回傳 JSON 的 URL 是可以想像的,這也代表從 HTML 頁面透過 script 元素抓取 JSON 是可能的。

然而,一份 JSON 文件並不是一個 JavaScript 程式。為了讓瀏覽器可以在 <script> 元素執行,從 src 裡 URL 回傳的必須是可執行的 JavaScript。在 JSONP 的使用模式裡,該 URL 回傳的是由函數呼叫包起來的動態生成 JSON,這就是JSONP 的「填充(padding)」或是「前輟(prefix)」的由來。

慣例上瀏覽器提供回調函數的名稱當作送至伺服器的請求中命名查詢參數的一部份,例如:

 <script type="text/javascript"
         src="http://server2.example.com/RetrieveUser?UserId=1823&jsonp=parseResponse">
 </script>

伺服器會在傳給瀏覽器前將 JSON 數據填充到回調函數(parseResponse)中。瀏覽器得到的回應已不是單純的資料敘述而是一個腳本。在本例中,瀏覽器得到的是:

   parseResponse({"Name": "Cheeso", "Id" : 1823, "Rank": 7})

填充

雖然這個填充(前輟)「通常」是瀏覽器執行背景中定義的某個回調函數,它也可以是變數賦值、if 敘述或者是其他 JavaScript 敘述。JSONP 要求(也就是使用 JSONP 模式的請求)的回應不是 JSON 也不被當作 JSON 解析——回傳內容可以是任意的運算式,甚至不需要有任何的 JSON,不過慣例上填充部份還是會觸發函數調用的一小段 JavaScript 片段,而這個函數呼叫是作用在 JSON 格式的資料上的。

另一種說法—典型的 JSONP 就是把既有的 JSON API 用函數呼叫包起來以達到跨域存取的解法。

Script 元素「注入」

為了要啟動一個 JSONP 呼叫(或者說,使用這個模式),你需要一個 script 元素。因此,瀏覽器必須為每一個 JSONP 要求加(或是重用)一個新的、有所需 src 值的 <script> 元素到 HTML DOM 裡—或者說是「注入」這個元素。瀏覽器執行該元素,抓取 src 裡的 URL,並執行回傳的 JavaScript。

也因為這樣,JSONP 被稱作是一種「讓使用者利用 script 元素注入的方式繞開同源策略」的方法。

安全問題

使用遠端網站的 script 標籤會讓遠端網站得以注入任何的內容至網站裡。如果遠端的網站有 JavaScript 注入漏洞,原來的網站也會受到影響。

現在有一個正在進行計畫在定義所謂的 JSON-P 嚴格安全子集,使瀏覽器可以對 MIME 類別是「application/json-p」請求做強制處理。如果回應不能被解析為嚴格的 JSON-P,瀏覽器可以丟出一個錯誤或忽略整個回應。

跨網站的偽造要求

粗略的 JSONP 部署很容易受到跨網站的偽造要求(CSRF/XSRF)的攻擊。因為 HTML <script> 標籤在瀏覽器裡不遵守同源策略,惡意網頁可以要求並取得屬於其他網站的 JSON 資料。當使用者正登入那個其他網站時,上述狀況使得該惡意網站得以在惡意網站的環境下操作該 JSON 資料,可能洩漏使用者的密碼或是其他敏感資料。

只有在該 JSON 資料含有不該洩漏給第三方的隱密資料,且伺服器僅靠瀏覽器的同源策略阻擋不正常要求的時候這才會是問題。若伺服器自己決定要求的專有性,並只在要求正常的情況下輸出資料則沒有問題。只靠 Cookie 並不夠決定要求是合法的,這很容易受到跨網站的偽造要求攻擊。

歷史

2005 年夏天,喬治·詹姆提(George Jempty)建議在 JSON 前面選擇性的加上變數賦值。鮑勃·伊波利托(Bob Ippolito)於 2005 年 12 月提出了 JSONP 最原始的提案,其中填充部份已經是回調函數,而現在已有很多 Web 2.0 應用程式使用這份提案,像是 Dojo Toolkit 應用程式、Google Web Toolkit 應用程式與 Web 服務