JS里AJAX的使用--(同源策略,如何規避同源策略的jsonp)

同源策略:

什么是同源:只有在兩個頁面的協議(http://或者https://)、域名(www.baidu.com)、端口號(80端口,默認是80)都相同的情況下,這兩個頁面才是同源的。

同源策略限制的能力:非同源的兩個頁面,不能互相訪問對方設置的本機存儲數據、不能互相操作對方的DOM、ajax不能互相發送請求。

什么是跨域:在一臺服務器的頁面中,請求另一臺服務器的數據。這種行為就是跨域(兩個非同源服務器互相請求數據)。

AJAX規避同源策略(JSONP):

jsonp的本質:

1、利用標簽的src屬性可以加載任意服務器的接口內容的特性,把要請求的跨域服務器接口設置在該src屬性中,并憑借一個回調函數作為參數;

2、在服務器端收到請求后,取出傳進來的函數名,拼接成函數執行的形式,把前端需要的數據設置在函數參數中,一塊返還給前端;

3、前端在收到了服務器返回的函數執行碼時,開始觸發回調函數,在回調函數中就可以獲取到想要的數據了;

代碼如下:

// 1、創建script標簽

var scriptTag = document.createElement('script');

// 2、設置標簽類型

scriptTag.type = 'text/javascript';

// 3、設置請求的接口

scriptTag.src = 'http://10.0.153.197:8888/news?callback=getData';

// 4、拼接標簽進文檔流

window.onload = function() {

document.head.appendChild(scriptTag);

}

// 設置回調函數

function getData (data) {

console.log(data);

}


JSONP的客戶端具體實現:


1、我們知道,哪怕跨域js文件中的代碼(當然指符合web腳本安全策略的),web頁面也是可以無條件執行的。

遠程服務器remoteserver.com根目錄下有個remote.js文件代碼如下:

alert('我是遠程文件');

本地服務器localserver.com下有個jsonp.html頁面代碼如下:

<script type="text/javascript" src="http://remoteserver.com/remote.js">

毫無疑問,頁面將會彈出一個提示窗體,顯示跨域調用成功。



2、現在我們在jsonp.html頁面定義一個函數,然后在遠程remote.js中傳入數據進行調用。

remote.js文件代碼如下:

localHandler({"result":"我是遠程js帶來的數據"});

jsonp.html頁面代碼如下:

varlocalHandler=function(data){

alert('我是本地函數,可以被跨域的remote.js文件調用,遠程js帶來的數據是:'+data.result);

};

<script type="text/javascript" src="http://remoteserver.com/remote.js">

運行之后查看結果,頁面成功彈出提示窗口,顯示本地函數被跨域的遠程js調用成功,并且還接收到了遠程js帶來的數據。但是又一個問題出現了,我怎么讓遠程js知道它應該調用的本地函數叫什么名字呢?畢竟是jsonp的服務者都要面對很多服務對象,而這些服務對象各自的本地函數都不相同啊?我們接著往下看。





3、其實只要服務端提供的js腳本是動態生成的就行了,這樣調用者可以傳一個參數過去告訴服務端“我想要一段調用XXX函數的js代碼,請你返回給我”,于是服務器就可以按照客戶端的需求來生成js腳本并響應了。

看jsonp.html頁面的代碼:

//得到航班信息查詢結果后的回調函數varflightHandler=function(data){

alert('你查詢的航班結果是:票價'+data.price+'元,'+'余票'+data.tickets+'張。');

};

//提供jsonp服務的url地址(不管是什么類型的地址,最終生成的返回值都是一段javascript代碼)

var url="http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";

//創建script標簽,設置其屬性

var script=document.createElement('script');

script.setAttribute('src', url);

//把script標簽加入head,此時調用開始

document.getElementsByTagName('head')[0].appendChild(script);

這次的代碼變化比較大,不再直接把遠程js文件寫死,而是編碼實現動態查詢,而這也正是jsonp客戶端實現的核心部分,本例中的重點也就在于如何完成jsonp調用的全過程。

我們看到調用的url中傳遞了一個code參數,告訴服務器我要查的是CA1998次航班的信息,而callback參數則告訴服務器,我的本地回調函數叫做flightHandler,所以請把查詢結果傳入這個函數中進行調用。

OK,服務器很聰明,這個叫做flightResult.aspx的頁面生成了一段這樣的代碼提供給jsonp.html(服務端的實現這里就不演示了,與你選用的語言無關,說到底就是拼接字符串):

flightHandler({

"code": "CA1998",

"price": 1780,

"tickets": 5

});

我們看到,傳遞給flightHandler函數的是一個json,它描述了航班的基本信息。運行一下頁面,成功彈出提示窗口,jsonp的執行全過程順利完成!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • AJAX 原生js操作ajax 1.創建XMLHttpRequest對象 var xhr = new XMLHtt...
    碧玉含香閱讀 3,288評論 0 7
  • Section1、為什么要跨域? 自古以來(1995年起),為了用戶的信息安全,瀏覽器就引入了同源策略。那么同源策...
    qhaobaba閱讀 396評論 0 0
  • Section1、為什么要跨域? 自古以來(1995年起),為了用戶的信息安全,瀏覽器就引入了同源策略。那么同源策...
    不去解釋閱讀 581評論 0 0
  • 五十三:請解釋 JavaScript 中 this 是如何工作的。1.方法調用模式當一個函數被保存為一個對象的屬性...
    Arno_z閱讀 603評論 0 2
  • http://blog.tianya.cn/post-5339203-83776478-1.shtmlhttp:/...
    ef4502bffbeb閱讀 234評論 0 1