本人小白一枚,網(wǎng)上關于jsonp跨域的博文和回答實在是太多了,看到好多種虎谢??jsonp的方式,并沒有一一去嘗試有梆,可能原理都相同吧是尖,還沒有做深入了解,只是先記錄一下我所掌握的jsonp解決跨域的方法泥耀,希望和我一樣看的頭暈眼花的小伙伴能有所收獲~
1 同源策略
要理解跨域饺汹,先要了解“同源策略”,所謂同源是指痰催,域名兜辞,協(xié)議,端口相同夸溶。所謂“同源策略”逸吵,簡單的說就是基于安全考慮,當前域不能訪問其他域的東西缝裁。
一些常見的是否同源示例可參照下表:
在同源策略下扫皱,在某個服務器下的頁面是無法獲取到該服務器以外的數(shù)據(jù)的。例如我們在自己的網(wǎng)站通過ajax去獲取豆瓣提供的接口數(shù)據(jù)。即使是訪問本地非JS文件的文件(比如.json文件).
不過火狐可以正常讀取到韩脑,原因是:雖然允許跨域很不安全氢妈,但是如果不跨域的話又帶來很多不便,所以火狐是允許跨域的段多。
為什么谷歌獲取不到首量?
這里要提到一點,訪問本地計算機中的文件进苍,使用的是file協(xié)議加缘,file協(xié)議主要用來訪問本地計算機中的文件,就如同在windows資源管理器中打開文件一樣琅捏,注意它是針對本地(本機)的生百,簡單來說,file協(xié)議是訪問你本機的文件資源柄延。
谷歌的報錯可以在控制臺明顯看到:
Cross origin requests are only supported for protocol schemes:http蚀浆,data,chrome搜吧,chrome-extension市俊,https
實質(zhì)上就是安全機制認為加載本地其他文件是跨域行為。谷歌瀏覽器會跨域失敗滤奈,是因為瀏覽器安全機制不允許摆昧。
為什么谷歌不支持跨域?
這是因為瀏覽器的安全策略蜒程,即禁止ajax訪問本地的文件绅你,這是不安全也是不允許的,舉例的話昭躺,就相當于你訪問了一個網(wǎng)站忌锯,這個網(wǎng)站可以讀取到你本地的文件.......
2 跨域問題
Chrome真的很嚴格,對于Chrome來說领炫,訪問本地非js文件或者非同源地址都屬于跨域行為偶垮,而火狐可以訪問本地文件,但是訪問非同源地址時還是跨域的行為帝洪。
這類問題統(tǒng)稱為跨域問題似舵。
3 JSON
JSON是一種數(shù)據(jù)存儲格式,不懂得朋友可以自行百度一下~
3 JSONP的原理
JSONP是JSON的一種“使用模式”葱峡,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題砚哗,利用<script>元素的開放策略,網(wǎng)頁可以得到從其他來源動態(tài)產(chǎn)生的JSON資料砰奕,而這種使用模式就是所謂的JSONP频祝。用JSONP抓到的資料并不是JSON泌参,而是任意的JAVAScript,用javascript直譯器執(zhí)行而不是用JSON解析器解析常空。
動態(tài)創(chuàng)建<script>標簽沽一,設置其src,回調(diào)函數(shù)也在src中設置漓糙,例如:
<script src="(http://....其他域地址)/(文件地址)?(可以寫查詢內(nèi)容)&(callback=(回調(diào)函數(shù)的名稱))"> || <script src="index.json?callback=indexDemo"> 或者 <script src="https://api.douban.com/va/book/search?q=javascript&count=1&callback=handleResponse">
在頁面中铣缠,返回的JSON作為參數(shù)傳入回調(diào)函數(shù)中,我們通過回調(diào)函數(shù)來操作數(shù)據(jù)昆禽。
這里需要注意的是蝗蛙,JSON文件中的數(shù)據(jù)格式如下:
這里json數(shù)據(jù)前面的名稱要和第一條script標簽中的callback里的函數(shù)名稱一樣 indexDemo({ "hello":"bye" })
用過該方法的朋友會發(fā)現(xiàn)JSON文件會報錯,先別著急否定這個方法醉鳖,先讀一遍下面這段話~(詭異臉)
根據(jù)上述過程總結的話捡硅,JSONP的原理如下:
- 首先在客戶端注冊一個callback,然后把callback的名字傳給服務器盗棵。
- 此時服務器先生成JSON數(shù)據(jù)
- 然后以JS語法的方式壮韭,生成一個function,function名字就是傳遞上來的參數(shù)jsonp
- 最后將json數(shù)據(jù)直接以入?yún)⒌姆绞轿埔颍胖玫絝unction中喷屋,這樣就生成了一段Js語法的文檔,返回給客戶端瞭恰。
- 客戶端瀏覽器屯曹,解析script標簽,并執(zhí)行返回的Js文檔惊畏,此時數(shù)據(jù)作為參數(shù)恶耽,傳入到了客戶端預先定義好的callback函數(shù)里。
看到這里颜启,會不會有一種煥然大悟的感覺~原來.json文件中放置的是一個函數(shù)偷俭,只有是函數(shù),才可以將json數(shù)據(jù)以入?yún)⒌姆绞脚┣胖玫絝unction中。
4 JSONP的優(yōu)缺點
優(yōu)點
- 比XML輕了很多驻债,沒有那么多冗余的東西乳规。
- JSON具有很好的可讀性,但是通常返回的都是壓縮過后的合呐,不像XML這樣的瀏覽器可以直接顯示暮的,瀏覽器對于JSON的格式化顯示就需要借助一些插件了。
- 在JS中處理JSON很簡單
- 其他語言淌实,例如PHP對于JSON的支持也不錯
缺點
- JSON在服務端語言的支持不像XML那么廣泛冻辩,不過JSON.org上提供很多語言的庫(我并不懂這句話猖腕,以后再做研究)
- 如果你使用eval()來解析的話,會容易出現(xiàn)安全問題(依舊不懂恨闪,以后遇到再來補充~)
5 補充
JSONP是很強大的倘感,但不是所有跨域通信需求的萬靈藥,還是建議可以學會使用node或其他后端語言來配合完成跨域的方法~(雖然我也還沒學會咙咽,學會就會更新在博客里)
第一老玛,也是最重要的一點,沒有關于JSONP調(diào)用的錯誤處理钧敞,如果動態(tài)腳本插入有效蜡豹,就執(zhí)行調(diào)用;如果無效溉苛,就靜默失敗镜廉。失敗是沒有任何提示的,服務器既不會捕捉到404錯誤愚战,也不會取消或者重新開始請求娇唯。
第二,被不信任的服務使用時會很危險凤巨,因為JSONP服務返回打包在函數(shù)調(diào)用中的JSON相應视乐,而函數(shù)調(diào)用是由瀏覽器執(zhí)行的,這使宿主web應用程序更容易受到各類攻擊敢茁,如果打算使用JSONP服務佑淀,了解它能造成的威脅非常重要。
參考網(wǎng)址
輕松搞定JSONP跨域請求
AJAX跨域請求—JSONP獲取JSON數(shù)據(jù)