AJAX跨域呼叫相關知識 CORS和JSONP

2022-03-06 10:42:38 字數 3583 閱讀 8854

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

但是我們專案開發過程中,經常會遇到在乙個頁面的js**中,需要通過ajax去訪問另乙個伺服器並返回資料,這時候就會受到瀏覽器跨域的安全限制了。

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

乙個可以正常啟動的tomcat,預設埠8080;

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

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

兩個頁面是相同的,只是位址不同,都是在點選按鈕後通過ajax去訪問但是從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

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

接下來我們訪問

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

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

response.setheader(「access-control-allow-origin」, 「

response.setheader(「access-control-allow-origin」, 「*」);

小結:

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

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

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

$.support.cors = true;

jsonp並不是乙個官方協議,其本質上是一種巧妙的跨域獲取json資料的程式設計技巧。

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

首先執行這個頁面裡面ajax後端請求換成了add_jsonp.jsp。

接下來我們先解析**:

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

type改成了get,jsonp只支援get請求,這個引數在jsonp場景下其實是可以忽略的,即使改成post,也會依然按get模式;

datatype改成了jsonp,這個引數標明要採用jsonp方式進行呼叫;

jsonp: 「x5callback」,這個引數其實是乙個約定的引數名,用於後端按照這個引數名獲取乙個**函式名;

jsonpcallback:這個引數用來指定上面那個引數對應的**函式名,如果不指定,jquery會自動生成乙個隨機的函式名。

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

首先我們按照約定的引數名,獲取**函式名; string callbackname = request.getparameter(「x5callback」);

返回的內容格式也不再僅是乙個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模式,其實是動態建立了乙個標籤,標籤的src屬性指向乙個url(這個url裡面除了包含我們的a和b兩個引數,還包含乙個x5callback引數,引數的值就是那個隨機的函式名。這個script標籤動態插入到當前頁面後,自然就會將我們返回的內容當做js載入到當前頁面(這裡我們返回的是js,瀏覽器是不阻止的哦,頁面可以從任何域載入js指令碼):

debugger;jquery18203749695811420679_1439276096319()

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

小結:

jsonp是以動態建立script標籤為基礎的一種程式設計技巧,來實現跨域獲取json資料。

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

但是,要注意由於jsonp是以script標籤的src屬性載入的,因此引數會收到url長度的限制,只能適用於傳入引數內容不多的場景。

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

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

ajax跨域呼叫(例項)

我們在使用ajax通訊的時候,往往有時候可能會用向另外乙個專案或者向其他伺服器請求資料。這是我們就使用到了ajax跨域請求 客戶端 getjson https baiduyunservice servlet?jsoncallback function result else json 注意點 1.再...

Ajax跨域Cookie相關設定

在web程式設計中我們經常會遇到跨域的問題。預設情況下,瀏覽器是不允許跨域訪問的。所以說,在這裡就有乙個概念 cors cross origin resource sharing 跨域資源共享。在html5標準出來之前,cors是不被允許的。但是為了達到跨域訪問資源的目的,出現了很多較麻煩的方式 j...

ajax跨域實現api 介面呼叫

背景 想實現跨域去呼叫介面,然後同時支援下次呼叫,能夠帶cookie資訊過來,同時支援來自多個源頭的網域名稱的跨域呼叫。1.這樣支援來自所有網域名稱的跨域呼叫 不支援跨域是,瀏覽器報錯 在api介面服務端加上相應的協議頭 header access control allow origin head...