# 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
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.