瘋狂的JSONP

何爲跨域?何爲JSONP?JSONP技術能實現什麼?是否有必要使用JSONP技術?javascript

跨域

就是因爲JavaScript同源策略的限制,使得a.com域名下的js沒法操做b.com或c.a.com域名下的對象或數據。簡單理解同一個域就是:相同域名、相同端口、相同協議!css

同源策略

就是阻止從一個域上加載的腳本獲取或操做另外一個域上的文檔屬性。即受到請求的URL的域必須與當前Web頁面的域相同,意味着瀏覽器隔離來自不一樣源的內容,以防止它們之間的操做。html

「同源策略」的意義

「同源策略」有效地阻止了一些危險行爲,如你同時打開多個網站時,其中有一個木馬網站,那麼木馬網站就有可能竊取其餘網站上關於你的信息或資料(由於多個網站間是能夠相互通訊的),給網上用戶帶來很大的泄密風險。正是因爲有了「同源策略」,才大大下降了這種風險,因爲木馬網站與其餘你瀏覽的網站不一樣源,所以沒法相互間通訊訪問、獲取數據等。java

「同源策略」的不足

雖然「同源策略」在必定程度上保護了用戶的網絡安全,但若是有時就是須要讓www.aaa.com取得www.bbb.com上的數據,一樣是由於」同源策略」形成沒法從本身信任的其餘網頁上取得數據。jquery

URLajax

說明json

是否容許通訊跨域

http://www.a.com/a.js
http://www.a.com/b.js瀏覽器

同一域名下安全

容許

http://www.a.com/lab/a.js
http://www.a.com/script/b.js

同一域名下不一樣文件夾

容許

http://www.a.com:8000/a.js
http://www.a.com/b.js

同一域名,不一樣端口

不容許

http://www.a.com/a.js
https://www.a.com/b.js

同一域名,不一樣協議

不容許

http://www.a.com/a.js
http://70.32.92.74/b.js

域名和域名對應ip

不容許

http://www.a.com/a.js
http://script.a.com/b.js

主域相同,子域不一樣

不容許

http://www.a.com/a.js
http://a.com/b.js

同一域名,不一樣二級域名

不容許

http://www.cnblogs.com/a.js
http://www.a.com/b.js

不一樣域名

不容許

注意:

(1)若是是協議和端口形成的跨域問題,那麼對於JavaScript來講是無能爲力的。

(2)在跨域問題上,域僅僅是經過「URL首部」來識別而不會去判斷兩個域是否對應同一個IP地址。

JOSNP

爲了解決上面提到的需求,JSONP應運而生。其實JSONP在必定程度上彌補了AJAX的不足,即沒法跨域獲取數據。

那麼JSONP這貨究竟是怎麼來的,總不會是一羣工程師拍腦殼拍出來的吧?其實,任何技術、任何事情的來源都是有根源可尋的。

不知你們是否注意到,你是如何引用jQuery寫網頁的呢?是否就是在頁面中引入「<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>」便可,那麼這實際上是件頗有意思的事情!你們是否發現http://code.jquery.com/與你的網站地址確定是不一樣源的,那爲何還能在你的網頁中引用到jQuery呢?

是的,恍然大悟的時刻到了,其實JSONP就是利用這一點(能夠算是漏洞、也能夠算是技術吧)實現了跨域訪問數據。(其實有src屬性的不止<script>標籤,如<iframe>標籤也是可以運用JSONP技術的)。說白了,其實JSONP跨域技術本質上是建立<script>標籤,並經過其src指向跨域地址而實現跨域獲取數據。

JSONP原理

JSONP(JSON with Padding),就是異步請求跨域的服務器端時,不是直接返回數據,而是返回一個js方法,把數據做爲參數傳過來。若是隻是跨域傳遞數據那麼這種方式是比較好的。字面理解就是:利用內填充的原理,將json填充到一個box中的概念。

原理老是又饒又拗口,直接來個簡單的小例子吧!

在www.aaa.com 頁面中:

<script type="text/javascript"
src="http://www.bbb.com/jsonp.js"></script>
<script type="text/javascript">
function jsonp(json){
    alert(json[‘name’]); 
}
</script>

www.bbb.com/jsonp.js 中:

jsonp({'name':'twobin','age':24});

則頁面會彈出「twobin」,是否更爲直觀好理解一點呢!

咱們能夠取到www.bbb.com/jsonp.js,裏面是一個名爲jsonp的函數(這個函數名稱能夠自定義),這個函數也會被加載到www.aaa.com。加載完成後,就應該執行jsonp了,而後咱們在www.aaa.com定義jsonp函數,這個函數裏寫一些處理數據的語句。這樣其實就簡單地實現了跨域訪問數據了,這也就是JSONP的工做原理了。而「JSON with Padding」的意思,就是jsonp(json)中的json,即

{'name':'twobin','age':24}

這個JSON對象被包在jsonp這個函數中看成參數來被處理,而「JSON with Padding」這個詞很形象地形容了這個過程。

JSONP實例—百度搜索聯想

在百度首頁搜索框中其實就用到了JSONP技術,如咱們在百度搜索框中輸入json,則下拉框會自動給出多個相關的聯想詞,而這些聯想詞實際上是從另外一個不一樣源的域名中獲取的數據,經過JSONP技術獲取這些數據後實時的顯示在下拉列表中。

本文就是仿百度搜索聯想實現一個採用JSONP技術的例子。

1)解析數據地址

首先須要知道聯想詞數據的來源地址。在Chrome中的JavaScript控制檯下,查看Network,在百度搜索框中輸入關鍵詞,如「json」,則獲取到輸入「json」關鍵詞後傳回的數據。

其中,聯想詞數據的地址是:

http://suggestion.baidu.com/su?wd=json&p=3&cb=window.bdsug.sug&sid=&t=1383046774638

簡單解析下該地址,搜索關鍵字wd=‘json’,cb是一個回調函數,該回調函數是咱們取到數據要後執行的函數,在百度搜索中回調後執行函數window.bdsug.sug。點擊該地址連接,能夠獲得下列數據:

window.bdsug.sug({q:"json",p:false,s:["json格式","json在線解析","json解析","jsonp","jsonobject","json編輯器","jsonarray","json encode","json.stringify","json decode"]});
即這些聯想詞數據包含在函數window.bdsug.sug內做爲參數傳遞給百度搜索首頁,證實了JSONP跨域技術的可行性。

2)動態獲取跨域數據

既然是利用<script>標籤的src地址來獲取跨域數據,就不能將src地址寫死,而應該根據需求動態獲取跨域數據,所以須要根據需求動態生成<script>標籤後動態指定src地址。

var oScript = document.createElement('script');
oScript.src = 'http://suggestion.baidu.com/su?wd='+oTxt.value+'&p=3&cb=baidu&from=superpage';
document.body.appendChild(oScript);

注意:動態生成<script>標籤時會產生代碼冗餘,因爲咱們每輸入一個字符,頁面就會動態生成一個<script>標籤,一旦咱們輸入的字符繁多且不一樣,頁面就會實時生成衆多的冗餘標籤,所以須要在咱們輸入字符前檢查是否存在冗餘的<script>標籤,若是存在則將其刪除,從而避免代碼冗餘。

if(oScript){
    document.body.removeChild(oScript);
}

有博友提問:Google中的搜索聯想貌似跟百度中的不同?

Google中的搜索聯想並非經過callback回調函數執行的,如在google首頁搜索框中輸入「j」,則返回連接爲:https://www.google.com.hk/complete/search?client=hp&hl=zh-CN&gs_rn=32&gs_ri=hp&cp=1&gs_id=65&q=j&xhr=t;顯然google中的搜索聯想是經過ajax技術實現無刷新實時返回聯想數據的。

效果展現

相關文章
相關標籤/搜索