跨域?他是瀏覽器的同源策略造成的,是瀏覽器對javascript施加的安全限制。所謂同源是指:域名、協(xié)議、端口均相同。
解決
方式一:script標(biāo)簽實現(xiàn)跨域(jsonp)
原理:利用標(biāo)簽具有可跨域的特性,可實現(xiàn)跨域訪問接口,需要后端的支持。
var messagetow = function(data){
????alert(data);? ?//后端返回的json格式的數(shù)據(jù)
};
var url = "http://192.168.31.137/train/test/jsonpthree?callback=messagetow";
var script = document.createElement('script');
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
服務(wù)器在收到請求后,解析參數(shù),計算返還數(shù)據(jù),輸出messagetow(data)字符串。
缺點:只能發(fā)送get請求,無法訪問服務(wù)器的響應(yīng)文本(單向請求),即只能獲取數(shù)據(jù)不能改數(shù)據(jù)。
方式二:ajax的jsonp跨域(jsonp)
通過ajax請求不同域的實現(xiàn),底層不是靠XmlHttpRequest而是script,所以不要被這個方法給迷惑了。
在ajax請求中類型如果是type是get post,其實內(nèi)部都只會用get,因為其跨域的原理就是用的動態(tài)加載script的src,所以我們只能把參數(shù)通過url的方式傳遞
$.ajax({
url:' http://192.168.31.137/train/test/jsonpthree',? ? //不同的域
type: 'GET',? ? //jsonp模式只有GET是合法的
dataType: 'jsonp',? ? //數(shù)據(jù)類型
jsonp: 'callback',? ? ?//指定回調(diào)函數(shù)名,與服務(wù)器端接收的一致,并回傳回來
jsonpCallback:' messagetow ',
success:function(data){? ??
????alert(data.price);
},
error:funciton(){
}
})
其實jquery內(nèi)部會轉(zhuǎn)化成
http://192.168.31.137/train/test/jsonpthree?callback=messagetow
然后動態(tài)加載http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron">
http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron"><script type="text/javascript" src="http://192.168.31.137/train/test/jsonpthree?callback=messagetow"></script>
http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron">
http://192.168.1.114/yii/demos/test.php?backfunc=jQuery2030038573939353227615_1402643146875&action=aaron">
方式三:CORS
Cross-Origin Resource Sharing(CORS)跨域資源共享是一份瀏覽器技術(shù)的規(guī)范,提供了 Web 服務(wù)從不同域傳來沙盒腳本的方法,以避開瀏覽器的同源策略,確保安全的跨域數(shù)據(jù)傳輸。現(xiàn)代瀏覽器使用CORS在API容器如XMLHttpRequest來減少HTTP請求的風(fēng)險來源。與 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。服務(wù)器一般需要增加如下響應(yīng)頭的一種或幾種:
Access-Control-Allow-Origin:*
Access-Control-Allow-Methods:POST, GET, OPTIONS
Access-Control-Allow-Headers:X-PINGOTHER, Content-Type
Access-Control-Max-Age:86400
跨域請求默認(rèn)不會攜帶Cookie信息,如果需要攜帶,請配置下述參數(shù):
"Access-Control-Allow-Credentials":true//Ajax設(shè)置
"withCredentials":true
方式四:window.name+iframe
?window.name通過在iframe(一般動態(tài)創(chuàng)建i)中加載跨域HTML文件來起作用。然后,HTML文件將傳遞給請求者的字符串內(nèi)容賦值給window.name。然后,請求者可以檢索window.name值作為響應(yīng)。
iframe標(biāo)簽的跨域能力;
window.name屬性值在文檔刷新后依舊存在的能力(且最大允許2M左右)。
每個iframe都有包裹它的window,而這個window是top window的子窗口。contentWindow屬性返回<iframe>元素的Window對象。你可以使用這個Window對象來訪問iframe的文檔及其內(nèi)部DOM。
方式五:window.postMessage()
? HTML5新特性,可以用來向其他所有的 window 對象發(fā)送消息。需要注意的是我們必須要保證所有的腳本執(zhí)行完才發(fā)送 MessageEvent,如果在函數(shù)執(zhí)行的過程中調(diào)用了它,就會讓后面的函數(shù)超時無法執(zhí)行。
方式六:修改document.domain跨子域
?前提條件:這兩個域名必須屬于同一個基礎(chǔ)域名!而且所用的協(xié)議,端口都要一致,否則無法利用document.domain進(jìn)行跨域,所以只能跨子域
? 在根域范圍內(nèi),允許把domain屬性的值設(shè)置為它的上一級域。例如,在”aaa.xxx.com”域內(nèi),可以把domain設(shè)置為 “xxx.com” 但不能設(shè)置為 “xxx.org” 或者”com”。
? 現(xiàn)在存在兩個域名aaa.xxx.com和bbb.xxx.com。在aaa下嵌入bbb的頁面,由于其document.name不一致,無法在aaa下操作bbb的js??梢栽赼aa和bbb下通過js將document.name = 'xxx.com';設(shè)置一致,來達(dá)到互相訪問的作用。
方式七:WebSocket
WebSocket protocol 是HTML5一種新的協(xié)議。它實現(xiàn)了瀏覽器與服務(wù)器全雙工通信,同時允許跨域通訊,是server push技術(shù)的一種很棒的實現(xiàn)。相關(guān)文章,請查看:WebSocket、WebSocket-SockJS
**需要注意:**WebSocket對象不支持DOM 2級事件偵聽器,必須使用DOM 0級語法分別定義各個事件。
方式八:代理
同源策略是針對瀏覽器端進(jìn)行的限制,可以通過服務(wù)器端來解決該問題,例如nginx
DomainA客戶端(瀏覽器) ==> DomainA服務(wù)器 ==> DomainB服務(wù)器 ==> DomainA客戶端(瀏覽器)