由于瀏覽器存在同源策略機制蜓竹,同源策略阻止從一個源加載的文檔或腳本獲取或設(shè)置另一個源加載的文檔的屬性荆几。
同源策略的判定規(guī)則:
如果兩個頁面擁有相同的協(xié)議蝶溶,端口嗜历,和主機,那么這兩個頁面就屬于同一個源抖所;
圖示例:
特別的:由于同源策略是瀏覽器的限制梨州,所以請求的發(fā)送和響應是可以進行,只不過瀏覽器不接受罷了田轧。
瀏覽器同源策略并不是對所有的請求均制約:
- 制約: XmlHttpRequest
- 無效: img暴匠、iframe、script等具有src屬性的標簽
兩種實現(xiàn)跨域請求的方式傻粘,JSONP和CORS
對比:
Jsonp只支持 GET 請求每窖,CORS支持所有類型的HTTP請求帮掉。
Jsonp 的優(yōu)勢在于支持老式瀏覽器,以及可以向不支持CORS的網(wǎng)站請求數(shù)據(jù)岛请。
(1) JSON-P實現(xiàn)跨域請求
利用script標簽的src屬性(瀏覽器允許script標簽跨域)。
基本原理:
- 瀏覽器創(chuàng)建script標簽警绩,并利用script標簽的src屬性發(fā)送跨域請求崇败,獲取服務器的返回值在<script>標簽內(nèi)。
- 服務器返回函數(shù)調(diào)用語句(myfunc(args);)肩祥,并將需要返回的值(args)作為函數(shù)參數(shù)一并返回后室。
- 瀏覽器執(zhí)行服務器返回的調(diào)用函數(shù)的語句(myfunc(args)),對返回值進行操作。
- 瀏覽器刪除第一步創(chuàng)建的script標簽混狠。
代碼實例:
<p>
<input type="button" onclick="getJsonp();" value='提交'/>
</p>
JS實現(xiàn):
//創(chuàng)建script標簽跨域請求
function getJsonp(){
var tag = document.createElement('script');
tag.src = "http://tkq2.com:8000/test";
document.head.appendChild(tag);
document.head.removeChild(tag);
}
//根據(jù)返回函數(shù)myfunc([1,2,3]);執(zhí)行定義的myfunc函數(shù)
function myfunc(list) {
console.log(list);
}
Jquery實現(xiàn):
//創(chuàng)建script標簽跨域請求
function getJsonp(){
$.ajax({
url: "http://tkq2.com:8000/test",
dataType: 'jsonp',
jsonpCallback: 'myfunc'
})
}
其中jsonpCallback岸霹,自定義了回調(diào)函數(shù)名,默認為jQuery自動生成的隨機函數(shù)名将饺。如果不寫回調(diào)函數(shù)名贡避,默認執(zhí)行與服務器返回的函數(shù)名相同的函數(shù)。
//根據(jù)返回函數(shù)myfunc([1,2,3]);執(zhí)行定義的myfunc函數(shù)
function myfunc(list) {
console.log(list);
}
以上兩種寫法中予弧,回調(diào)函數(shù)被服務端寫死了刮吧,請求端必須定義和服務器端相同函數(shù)名才行。但作為服務端應該有更好的兼容性掖蛤,請求端自行決定回調(diào)函數(shù)名字杀捻。
JS實現(xiàn):
//創(chuàng)建script標簽跨域請求,并根據(jù)返回函數(shù)myfunc([1,2,3]);執(zhí)行定義的myfunc函數(shù)
function GetJsonp(){
var tag = document.createElement('script');
//自定義回調(diào)函數(shù)名蚓庭,jsonpcallback=myfunc字段供服務端讀取致讥。
tag.src = "http://tkq2.com:8000/test?jsonpcallback=myfunc";
document.head.appendChild(tag);
document.head.removeChild(tag);
}
function myfunc(list) {
console.log(list);
}
Jquery實現(xiàn)
//創(chuàng)建script標簽跨域請求,并根據(jù)返回函數(shù)myfunc([1,2,3]);執(zhí)行定義的myfunc函數(shù)
function GetJsonp(){
$.ajax({
url: "http://tkq2.com:8000/test",
dataType: 'jsonp',
jsonp:'jsonpcallback', //傳遞給請求處理程序或頁面的器赞,用以獲得jsonp回調(diào)函數(shù)名的參數(shù)名(一般默認為:callback)
jsonpCallback:'myfunc' //自定義了回調(diào)函數(shù)名垢袱,默認為jQuery自動生成的隨機函數(shù)名。如果不寫回調(diào)函數(shù)名港柜,默認執(zhí)行與服務器返回的函數(shù)名相同的函數(shù)惶桐。
})
}
//回調(diào)函數(shù)
function myfunc(list) {
console.log(list);
}
(2) CORS跨域資源共享
隨著技術(shù)的發(fā)展,現(xiàn)在的瀏覽器可以支持主動設(shè)置從而允許跨域請求潘懊,即:跨域資源共享(CORS姚糊,Cross-Origin Resource Sharing),其本質(zhì)是設(shè)置響應頭授舟,使得瀏覽器允許跨域請求救恨。
這種實現(xiàn)方式:請求端和普通的AJAX方法相同,但服務器端需要做相應的配置释树。
跨域傳輸cookie:
在跨域請求中肠槽,默認情況下擎淤,HTTP Authentication信息,Cookie頭以及用戶的SSL證書無論在預檢請求中或是在實際請求都是不會被發(fā)送秸仙。
如果想要發(fā)送:
瀏覽器端:XMLHttpRequest的 withCredentials 為 true (如果后臺需要傳cookie嘴拢,則設(shè)置,否則寂纪,不用設(shè)置)
服務器端:Access-Control-Allow-Credentials 為 true
$.ajax({
url: ajaxUrlConfig.getAddOrder,
data: data,
type: 'POST',
xhrFields: {
withCredentials: true
},
dataType: 'json',
timeout: 300000
});