# Explain how JSONP works (and how it's not really Ajax). ### JSONP 是 利用 `src` 不受同源限制的特性,直接載入一支帶參數的`.js`,當作是發 request 給 server,而 server 回傳的資料會用一個 function 包裝起來。 - 什麼是JSONP: JSONP的全名是 JSON with Padding,是 JSON 的一種使用模式,可以讓一個網頁從其他的網域 (cross-domain) 請求資料,繞過 AJAX 因為有瀏覽器安全性限制無法跨網域使用的問題 (same-origin policy)。 - 什麼是Same-origin policy([同源政策](https://developer.mozilla.org/zh-TW/docs/Web/Security/Same-origin_policy)) 同源策略是一個重要的安全機制,它限制了從一個來源(A來源)加載的文件或腳本與另一個來源(B來源)進行資源互動的方式。 - 什麼樣的情況算是同源 > 同源:兩份網頁具備相同協定、埠號 (如果有指定) 以及主機位置  所以,不同協定 (`http` 和 `https`) 就是不同源、port不同就是不同源、不同domain就是不同源。當我們接別人的API時,多數就是不同源的情況。 - 同源政策如何運作 如果從目前瀏覽器的網頁向跟自己「不同源」的網址發出請求和存取資料,就是被視作「跨來源存取」,一般情況下是不允許的,只有「同源」才會被允許。 > 原因:這是基於網絡安全的考量,避免有駭客惡意呼叫其他人的網絡服務。若沒有這個政策保護,別人就可以任意修改和存取你網頁裏的資源了。 - **同源政策並非完全禁止跨來源存取 ( → JSONP 可以執行的原因)** 但在某些情況下,即使兩個網站是「不同源」,也可以允許存取的。例如以下情況: 1. 跨來源寫入(Cross-origin writes) 例如允許:表單送出(form)、連結(link)、重新導向(redirect) 2. **跨來源嵌入(Cross-origin embedding)** 例如允許:嵌入圖片`<img>`、影片`<video>`、`<iframe>`、放在`<script>`裏的程式碼、CSS stylesheet `<link rel="stylesheet" href="...">`等等(只要有 `src`這個屬性的標籤都可以)。 ### JSONP是怎麼執行的 - JSONP由兩部分組成:回調函數(callback function)和數據(data)。 - callback function:一般是在瀏覽器控制,作為參數發往伺服器端(也可以固定回調函數的名字,但瀏覽器端和伺服器端的名稱一定要一致)。 - data:當伺服器回應request時,就會把該function和data拼成字符串返回。 - 執行步驟 1. 瀏覽器以JSONP格式發送request 1. 請求階段:瀏覽器創建一個 `script` 標籤,並給其`src` 賦值。 2. 發送請求:當給`script`的`src`賦值時,瀏覽器就會發起一個請求。 ```jsx <!-- https://mydomain.com --> <script> function printData(data) { console.log(`My name is ${data.name}!`); } </script> <script src="https://example.com?callback=printData"></script> ``` 2. 遠端伺服器接收到請求後,會把data包在一個叫做 `printData` 的函數中回傳。 ```jsx // File loaded from https://example.com?callback=printData printData({name: 'Yang Shun'}); ``` 3. 最後在 callback function 中,就可以對 server 返回的資料做任何事啦。 - 一些限制: - 實務上在操作 JSONP 的時候,server 通常會提供一個 callback 的參數讓 瀏覽器端帶過去。但 JSONP 的缺點就是你要帶的那些參數「**永遠都只能用附加在網址上的方式(GET)帶過去,沒辦法用 POST** 」。 - 要使用 JSONP 傳送資料,**也要 Server 端有提供 JSONP 的方法**(意指用 callback function 包起來)才行,不然回傳的 Response 就只是字串而已,沒有辦法取得資料。 ### 跟AJAX的差異 - 什麼是 Ajax (Asynchronous JavaScript and XML) Ajax 是指伺服器回應瀏覽器發送的請求,透過 JavaScript 用非同步的方法來傳送資料(透過`XMLHttpRequest`物件),在不重新載入頁面的情況下更新的技術。 - 例如:FB 的按讚、登入而不離開網頁、投票與評分等都是 Ajax 技術的應用。 - 運作原理:瀏覽器實例化`XMLHttpRequest`物件,使用此物件與server互動。 - 流程: 1. 瀏覽器發送一個帶上參數的 request (`XMLHttpRequest`物件) 給 server 2. server接收到request後,回傳 response 給瀏覽器 - 什麼是`XMLHttpRequest`: `XMLHttpRequest` 物件提供 `GET ` 及 `POST` 兩種不同的方法來傳送資料給瀏覽器,**採用何種方式需視伺服器端如何設計而定**。 - `GET` 方法會將要傳送的索引資料接在 URL 之後,於 URL 欄可見,安全性較差,**適合不會影響伺服器端資料庫或檔案的請求**。 - `POST` 方法會將傳送的資料與 URL 分開,於 URL 欄可見,安全性較高,**當發出請求所傳送的資料會影響伺服器端資訊時較適用**。 - 差異 **從定義來找差異點** > JSONP 可以讓一個網頁從其他的**網域** (cross-domain) **請求資料**,繞過 AJAX 因為有瀏覽器安全性限制無法跨網域使用的問題 (same-origin policy)。 1. 網域:是否能跨來源存取 - Ajax:只要是跨域請求,一律不准 - JSONP:可以透過跨來源嵌入(`src`)的方式跨來源存取資料。 2. 請求資料 1. 請求方式 - Ajax:透過 `XMLHttpRequest` 物件 - JSONP:透過 `<script>`標籤 2. HTTP Method - Ajax:可以用 `GET` 和 `POST` - JSONP:只能用 `GET` ### 補充 - JSONP的風險 一般 JSONP 不會設計用來傳輸隱私性高的資料,因為JSONP是JavaScript,它可以做任何JavaScript可以做的事,容易遭受到像是 CSRF (跨站請求偽造) 攻擊的安全性問題(所以你必須信任提供 JSONP 資料的人)。 > 近來,較推薦的方法是CORS (跨來源資源共用),JSONP會被當作是HACK行為。 - CSRF (Cross Site Request Forgery, 跨站請求偽造) - 也會被縮寫成 XSRF - 例如,小明有一個部落格,可以透過點擊刪除按鈕刪掉文章。 ```jsx <a href='/delete?id=3'>刪除</a> ```  假設小黑是一個邪惡的壞蛋,想要讓小明在不知情的情況下就把自己的文章刪掉,該怎麼做呢? ```jsx <img src='https://small-min.blog.com/delete?id=3' width='0' height='0' /> <a href='/test'>開始測驗</a> ``` 小黑偽造了一個心理測驗的網址傳給小明,上面那段程式的內容做的事情是:在開啟頁面的同時,發送一個刪除的 request 出去。 點擊之後瀏覽器就會發送一個 GET 請求給`https://small-min.blog.com/delete?id=3`,並且因為瀏覽器的運行機制,一併把 `small-min.blog.com` 的 cookie 都一起帶上去。 Server 端收到之後檢查了一下 session,發現是小明,而且這篇文章也真的是小明發的,於是就把這篇文章給刪除了。 > 這就是 CSRF,你現在明明在心理測驗網站,假設是 `https://test.com` 好了,但是卻在不知情的狀況下刪除了 `https://small-min.blog.com` 的文章,你說這可不可怕?超可怕! 這也是為什麼 CSRF 又稱作 one-click attack 的緣故,你只要點一下就中招了。 - CSRF 就是**在不同的 domain 底下卻能夠偽造出「使用者本人發出的 request」**。要達成這件事也很簡單,因為瀏覽器的機制,你只要發送 request 給某個網域,就會把關聯的 cookie 一起帶上去。如果使用者是登入狀態,那這個 request 就理所當然包含了他的資訊(例如說 session id),這 request 看起來就像是使用者本人發出的。 - 深入了解: [讓我們來談談 CSRF](https://blog.techbridge.cc/2017/02/25/csrf-introduction/) - CORS (Cross-Origin Resource Sharing, 跨來源資源共用) - 是一種使用額外 HTTP 標頭,令目前瀏覽網站的使用者代理(例如 `XMLHttpRequest` 或 `Fetch API`)取得存取其他來源(網域)伺服器特定資源權限的機制。 - 實作: 只要 Server 端在 response 的 header 加上一行,就可以允許不同網域的 request 存取 ```javascript access-control-allow-origin: * ``` 除了這個 Header 以外,其實還有其他的可以用,例如說 `Access-Control-Allow-Headers` 跟 `Access-Control-Allow-Methods`,就可以定義接受哪些 Request Header 以及接受哪些 Method。 - JSONP 和 JSON 的關係 JSONP 和 JSON 其實也沒有什麼直接的關係,只是搭配 JSON 是純文字格式方便傳輸且支援豐富的資料交換格式的特點。另外因為 JavaScript 原生就可以直接操作 JSON,讓 JSONP 這個使用模式更方便好用。 - 參考資料 - Ajax & JSONP [輕鬆理解 Ajax 與跨來源請求](https://blog.techbridge.cc/2017/05/20/api-ajax-cors-and-jsonp/) [JSONP - JSON 教學 Tutorial](https://www.fooish.com/json/jsonp.html) [[第十週] week 8 複習 - Ajax、JSONP](https://yakimhsu.com/project/project_w10_review_Ajax_JSONP.html) [Jsonp 關鍵字詳解及json和jsonp的區別,ajax和jsonp的區別](https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC/271374/) [](https://kknews.cc/zh-tw/code/2zyxzz9.html) [JSON和JSONP的區別詳解](https://www.itread01.com/content/1548899848.html) [Ajax---[ Ajax、JSON、JSONP ]---無用小觀念 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10187942) - 同源政策 [同源政策 (Same-origin policy) - Web 安全 | MDN](https://developer.mozilla.org/zh-TW/docs/Web/Security/Same-origin_policy) [JavaScript基本功修練:Day30 - AJAX常遇上的同源政策問題與解決方法 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10253549) - CORS [跨來源資源共用(CORS) - HTTP | MDN](https://developer.mozilla.org/zh-TW/docs/Web/HTTP/CORS)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up