簡單理解jsonp原理

来源:http://www.cnblogs.com/cyniczzz/archive/2016/06/21/5605066.html
-Advertisement-
Play Games

對於javascript程式員來說,發送ajax請求獲取後臺數據然後把數據和模板拼接成字元串渲染回DOM實現無刷新更新頁面這樣的操作可謂是輕車熟路。但眾所周知,ajax有一個不好,就是不能跨域傳輸數據,而跨域傳輸有時候又是必須用到的,比如我們可能需要調用第三方網站提供的某些API來獲取某些信息,提供 ...


對於javascript程式員來說,發送ajax請求獲取後臺數據然後把數據和模板拼接成字元串渲染回DOM實現無刷新更新頁面這樣的操作可謂是輕車熟路。但眾所周知,ajax有一個不好,就是不能跨域傳輸數據,而跨域傳輸有時候又是必須用到的,比如我們可能需要調用第三方網站提供的某些API來獲取某些信息,提供給我們網站的用戶。   例如,要開發一個天氣應用,你可能需要調用第三方的天氣API,這個時候就必然涉及到跨域請求數據,因為畢竟我們不可能為了開發一個天氣應用就自己搭建一個天氣API。在少數情況下,如果第三方網站的伺服器上設置了CORS機制,這時是可以直接用ajax發送請求的。但在大多數情況下,第三方網站都沒有這麼慷慨,因為涉及到安全問題,不可能允許任意人都能自由調用自己網站的介面。這個時候jsonp就應運而生了。   在HTML中有這樣一類標簽,它們都有一個src屬性,src屬性的值是一個鏈接,當標簽一被解析到DOM中,就會開始把src屬性中的鏈接指向的資源下載到本文檔,例如,設置了src的img標簽會自動從src屬性的鏈接中下載資源,下載的資源又會被瀏覽器解析成圖片,加到DOM中;設置了src屬性的iframe元素會從src鏈接里下載一張網頁;設置了src屬性的script元素也會自動從src鏈接里下載javascript代碼並執行,而這個過程中DOM本身也是沒有刷新的,更令人心動的是,src屬性的鏈接根本沒有同域的限制。這個原理就是實現JSONP的基石。   但是,我們想用它來實現跨域還很有難度。這個src屬性的元素的載入和一般的ajax請求有一個很大的不同,回想一下,在一個典型的ajax請求中,我們可以完全控制請求的過程,我們可以對指定的網頁實行open,可以設置請求頭,可以指定響應的MIMEtype,關鍵的是,我們可以從xhr對象的responseText屬性中獲取響應數據,然後拼接模板,渲染DOM。但在img, iframe, script這些標簽中呢,我們的控制權就被剝奪了,我們設置src屬性,瀏覽器負責發送請求,伺服器端返回的響應直接就被載入回DOM了,我們根本沒有插手修改數據的機會。   怎麼辦呢?這就像向遙遠的深空發射一艘飛船,當飛船遠離我們幾十光年的時候,我們就不太可能從地面對它發送實時控制信號了,更好的做法就是把指令提前寫在飛船上,讓它自動執行。   和飛船的例子一樣,一個典型的jsonp過程就是:創建一個script標簽,設置src屬性,這個src屬性中包括了目標API的地址,我們的查詢字元串querystring,querystring中最最重要的是我們的“指令”,因為script標簽src返回之後,我們並不能控制返回的結果,所以最好讓伺服器返回的時候自己執行我們想要執行的操作。這個“指令”也就是jsonp中的“p”了。   舉一個慄子: 1.我需要某個數據,比如就按照前面講的,天氣數據吧,於是我構造查詢url。
var script = document.createElement('script');
script.src = 'www.weather.fake/get/?province=hubei&city=wuhan&callback=instruction';
document.getElementsByTagName('head')[0].appendChild(script);
//先寫好指令,即回調 function instruction(data){ console.log(data); } //註意這裡的instruction就是我們告訴伺服器的“指令”。我們跟伺服器說,我需要province為hubei,city為wuhan的地方的天氣數據,但由於數據返回後我自己不能處理,所以你返回數據的時候自己處理好了,具體怎麼處理,我已經寫在名字叫做instruction的指令裡面了。

 

2.weather.fake的伺服器收到我的請求,從資料庫里一找,找到了數據。一看,還有個指令,於是它就執行instruction指令。說起來很高級,實際上也就是把返回的數據包裹在instruction函數裡面(jsonp的p,padding)。伺服器於是返回這樣一個東西:
//response.js
instruction({
  "city":"wuhan",
  "weather":"cloudy"
})
  3.伺服器端的writeheader設置和瀏覽器端的accept設置會保證返回的東西會被瀏覽器解釋成一個js文件,於是我們事先寫好的指令instruction函數就得到了執行,整個jsonp過程就完成了。   需要註意的幾點:   1.返回的js文件是在全局作用域執行的,所以你要保證你寫的回調函數instruction在全局作用域里。     2.這裡的callback=instruction。其中,callback只是一個普通的querystring,是你和伺服器事先約定的,不同API提供方,名字也不同,有的可能就叫cb,等等。至於instruction,你愛寫什麼寫什麼,但要保證和你寫的回調處理函數名字一致。我這裡為了方便理解,就寫instruction了。   餘論:ajax跨域,危險在哪裡? 有些人說,禁止ajax跨域,是為了防止攻擊者利用它向自己的伺服器發送敏感信息(例如cookie等等),這顯然是錯誤的。對於一個已經被註入攻擊代碼的網站,攻擊者如果只是想向自己的伺服器發送信息而已,就算不用ajax,也完全可以用img等標簽直接向自己的伺服器執行get請求發送數據,況且創建一個img標簽可比寫一個完整的ajax過程簡單多了,根本用不著興師動眾,也就是說,單向GET請求ajax並沒有優勢。   為什麼要限制ajax,因為它太強大了。看看CORS機制,它規定的是伺服器方面的接受白名單。也就是說,由伺服器來決定可以接受哪些客戶可以向它請求數據。說明跨域限制主要是為了保證伺服器端安全的。   一般能用src做到的,ajax都能做到,ajax能做到的src卻不一定能夠做到。例如src只能發起get請求,但ajax能發起任意類型的請求。   舉個慄子,某博客網站的刪除文章功能API可能必須要用DELETE方法發送請求才能執行,這個時候攻擊者如果只用src構造請求就無能為力了,但ajax卻可以輕易模擬用戶動作。這個時候禁止跨域就顯得很重要了。   具體過程:假設我的攻擊網站是www.evil.com。而一個允許CORS跨域傳輸ajax的博客網站是www.blog.com。該博客網站中,當用戶點擊了刪除按鈕時,就會向伺服器發送DELETE請求。具體為:www.blog.com/user/delete(?id=10000)(由於是DELETE方法,實際上querystring是不會附在url上的,這裡為了便於說明而已。)這個時候,假如用戶訪問我的evil.com網站,而我在我網站的腳本里寫ajax $.ajax({     url:'www.blog.com/user/delete',     method:'delete',     data:{id:10000}, }) 這樣是能成功的,因為當發送ajax時,會自動帶上用戶在www.blog.com的cookie,而請求方法又合法,所以完全能取得blog.com伺服器的信任,也就能不知不覺地刪除用戶在blog.com上寫的文章。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 二、允許網頁寬度自動調整 "自適應網頁設計"到底是怎麼做到的?其實並不難。 首先,在網頁代碼的頭部,加入一行viewport元標簽。 <meta name="viewport" content="width=device-width, initial-scale=1" /> viewport是網頁默 ...
  • 1、控制橫向和縱向滾動條的顯隱? <body style=”overflow-y:hidden”> 去掉x軸 <body style=”overflow-x:hidden”> 去掉y軸 <body scroll=”no”>不顯 2、表格變色 <TD onmouseover=”this.style.b ...
  • 移動開發這些年,移動開發者人數越來越多,類似的培訓公司發展也很快,不過伴隨著的是移動應用的需求這幾年發展更為旺盛。要開發好的App,純原生開發肯定是最佳選擇。但是這麼多年發展,原生開發的難度並沒有降低多少,特別是作為一個需要長期運營的App,需要原生人員的長期跟進,人員成本很高。另外,從蘋果和And ...
  • 未採用生僻的jquery特性,能相容jquery1.2.6以上所有版本 實例預覽 引入文件 複製 使用方法 複製 複製 soColorPacke參數 複製 下載 ...
  • 寫的一個XML操作類,包括讀取/插入/修改/刪除。 using System;using System.Data;using System.Configuration;using System.Web;using System.Web.Security;using System.Web.UI;usi ...
  • 最近項目中總是調來調去的介面,理解不深甚是糊塗,遂簡單整理一下也方便今後查用。 【字元串轉換為對象】 parse用於從一個字元串中解析出json對象,如 var str = '{"name":"demo","age":"22"}' 結果: JSON.parse(str) Object age: "2 ...
  • 一、在上下結構的div佈局中,可能出現div覆蓋div,但是內容卻沒有出現覆蓋的現象。看看一個示例 1: <!DOCTYPE html> 2: <html> 3: <head> 4: <title>DIV與DIV覆蓋</title> 5: <meta http-equiv="Content-Type ...
  • <script type="text/javascript"> function getRandom(n,m){ var n=Number(n); //強制轉換成數字 var m=Number(m); if(isNaN(n)||isNaN(m)){ //判斷是否為有效數字 ,其中一個不是有效數字就返 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...