AJAX跨域調用相關知識-CORS和JSONP

來源:互聯網
上載者:User

標籤:

1、什麼是跨域

跨域問題產生的原因,是由於瀏覽器的安全機制,JS只能訪問與所在頁面同一個域(相同協議、網域名稱、連接埠)的內容。

但是我們項目開發過程中,經常會遇到在一個頁面的JS代碼中,需要通過AJAX去訪問另一個伺服器並返回資料,這時候就會受到瀏覽器跨域的安全限制了。

 

這裡要注意,如果只是通過AJAX向另一個伺服器發送請求而不要求資料返回,是不受跨域限制的。瀏覽器只是限制不能訪問另一個域的資料,即不能訪問返回的資料,並不限制發送請求。

我們接下來就為大家講解最常見的跨域AJAX調用的解決方案,首先我們先準備一個測試環境:

  1. 一個可以正常啟動的Tomcat,預設連接埠8080;
  2. 下載範例程式碼包ajax-cors-jsonp.zip,解壓到Tomcat的webapps下,範例程式碼包中有test-client和test-service兩個檔案夾,分別包含我們樣本的用戶端和服務端代碼;
  3. 類比一個多域環境,修改“C:\Windows\System32\drivers\etc\hosts”(如果檔案不能編輯儲存,需要在檔案屬性中去掉唯讀),在檔案內容後面追加:

127.0.0.1       www.aaa.com 127.0.0.1       www.bbb.com

啟動Tomcat後,在瀏覽器中,分別測試

http://www.aaa.com:8080/test-client/index.html

http://www.bbb.com:8080/test-client/index.html

兩個頁面是相同的,只是地址不同,都是在點擊按鈕後通過AJAX去訪問http://www.bbb.com:8080/test-service/add.jsp。但是從www.aaa.com:8080訪問時就返回了error,即瀏覽器不允許在www.aaa.com:8080的頁面中通過AJAX擷取來自www.bbb.com:8080伺服器的返回資料。

大家觀察一下Tomcat控制台,會發現從www.aaa.com:8080訪問時,雖然返回了錯誤,但服務端代碼其實還是執行了。這個現象驗證了跨域是可以發請求的,但是瀏覽器出於安全的原因不讓我們在JS中擷取返回資料。

測試案例很簡單,就是傳入a=15&b=10兩個參數,返回兩個資料的和25,代碼參見:

test-client/index.html

test-service/add.jsp

2、CORS方案

本節介紹的CORS(Cross-Origin Resource Sharing)方案是W3C在2014年正式推出的跨域訪問方案,是真正的官方解決方案。這個方案的實現非常簡單,只需要在服務端返回的頭部資訊中標明是否允許跨域訪問,以及允許哪些域訪問即可。

接下來我們訪問

http://www.aaa.com:8080/test-client/index_cors.html

成功了!!!我們來看代碼中有什麼改變?

index_cors.html與index.html的差異僅是ajax調用的地址從add.jsp換成了add_cors.jsp,我們再來看add.jsp和add_cors.jsp的區別,會發現只增加了一行代碼:

response.setHeader(“Access-Control-Allow-Origin”, “http://www.aaa.com:8080”);

如果不限定跨域訪問的地址,可以把網域名稱部分設定為*:

response.setHeader(“Access-Control-Allow-Origin”, “*”);

小結:

CORS方案實現非常簡單,只要服務在頭部標明允許跨域訪問即可。但是這個方案由於推出時間較晚,所以IE9及以下瀏覽器並沒有支援這個機制。

IE9及以下瀏覽器在安全設定裡控制是否允許跨域資料訪問:

預設是上面的選項是禁用的,需要手動啟用。同時,由於jQuery自動判斷並認為當前瀏覽器不支援跨域,所以我們還需要用一行代碼讓jquery支援跨域ajax:

$.support.cors = true;

3、JSONP方案

JSONP並不是一個官方協議,其本質上是一種巧妙的跨域擷取JSON資料的編程技巧。

我們首先來看實現,JSONP在實現上要比CORS稍微麻煩一點點,前後端要有點配合。

首先運行http://www.aaa.com:8080/test-client/index_jsonp.html,這個頁面裡面AJAX後端請求換成了add_jsonp.jsp。

接下來我們先解析代碼:

index_jsonp.html中,我們在$.ajax的參數上有點變化:

  1. type改成了get,JSONP只支援get請求,這個參數在JSONP情境下其實是可以忽略的,即使改成post,也會依然按get模式;
  2. dataType改成了jsonp,這個參數標明要採用JSONP方式進行調用;
  3. jsonp: “x5callback”,這個參數其實是一個約定的參數名,用於後端按照這個參數名擷取一個回呼函數名;
  4. jsonpCallback:這個參數用來指定上面那個參數對應的回呼函數名,如果不指定,jQuery會自動產生一個隨機的函數名。

add_jsonp.jsp中,我們在最後資料返回部分做了一點處理:

  1. 首先我們按照約定的參數名,擷取回呼函數名; String callbackName = request.getParameter(“x5callback”);
  2. 返回的內容格式也不再僅是一個JSON資料,而是一個JS的函數調用形式:回呼函數名(JSON資料) String jsonpResult = String.format(“%s(%s)”, callbackName, jsonResult);

前後端需要做的工作就是這麼多,但是這時候初學者一定覺得有點迷惑了,這個回呼函數名到底是幹什麼用的?我們並沒有定義什麼回呼函數啊?它是怎麼工作的呢?

我們簡單的加一個調試很快就可以解開這個疑惑,在add_jsonp.jsp最終返回的資料中加一個debugger:

String jsonpResult = String.format(“debugger;%s(%s)”, callbackName, jsonResult);

接下來我們F12啟動瀏覽器開發人員工具,點擊按鈕後就會進入JS調試。

這時候我們看到返回的是一個JS函數的調用,函數名是隨機的,函數的參數就是那個我們構造的JSON。接下來,我們在控制台輸入window.函數名,會發現這個函數是真實存在的!!!

這是怎麼回事呢???原來jQuery所謂的JSONP模式,其實是動態建立了一個<script>標籤,標籤的src屬性指向一個URL(http://www.bbb.com:8080/test-service/add_jsonp.jsp?x5callback=jQuery18203749695811420679_1439276096319&a=15&b=10&_=1439276101932),這個URL裡面除了包含我們的a和b兩個參數,還包含一個x5callback參數,參數的值就是那個隨機的函數名。這個script標籤動態插入到當前頁面後,自然就會將我們返回的內容當做JS載入到當前頁面(這裡我們返回的是JS,瀏覽器是不阻止的哦,頁面可以從任何域載入JS指令碼):

debugger;jQuery18203749695811420679_1439276096319({“sum”: 25})

載入後,按照JS的特性,這些代碼會立即執行。而jQuery在這個之前已經動態建立了一個以隨機函數名為名稱的全域函數,用於接收返回資料,再往後jQuery通過一系列的邏輯代碼最終把傳回值給到了我們的success回呼函數中。

有關jQuery動態建立<script>相關的邏輯,大家可以在我們案例內建的jquery-1.8.2.js的8270行加上斷點進行跟蹤。

小結:

JSONP是以動態建立script標籤為基礎的一種編程技巧,來實現跨域擷取JSON資料。

支援目前所有瀏覽器,只是在實現方式上需要前後端代碼有一點約定配合。

但是,要注意由於JSONP是以script標籤的src屬性載入的,因此參數會收到URL長度的限制,只能適用於傳入參數內容不多的情境。

4、總結

CORS方案實現簡單,同時支援GET和POST請求,但是不支援IE9及以下瀏覽器。這時看官要問了,這麼多瀏覽器不支援,這技術怎麼用啊?手機啊!目前市面上所有的手機瀏覽器是全部支援CORS的,如果是為手機提供跨網域服務CORS就夠了。

JSONP方案實現需要前後端配合,支援GET請求,支援所有瀏覽器,只是傳入的參數內容受限於URL長度限制。

 

下載資源:ajax-cors-jsonp.zip

AJAX跨域調用相關知識-CORS和JSONP

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.