JavaScript跨域方法匯總
做Web開發(fā)經(jīng)常需要面對(duì)跨域問題,跨域問題的根源是瀏覽器安全中的同源策略,比如說,對(duì)于http://www.a.com/1.html來說:
1.http://www.a.com/2.html是同源的;
2.https://www.a.com/2.html是不同源的,原因是協(xié)議不同;
3.http://www.a.com:8080/2.html是不同源的,原因是端口不同;
4.http://sub.a.com/2.html是不同源的,原因是主機(jī)不同。
在瀏覽器中,<script>、<img>、<iframe>和<link>這幾個(gè)標(biāo)簽是可以加載跨域(非同源)的資源的,并且加載的方式其實(shí)相當(dāng)于一次普通的GET請(qǐng)求,唯一不同的是,為了安全起見,瀏覽器不允許這種方式下對(duì)加載到的資源的讀寫操作,而只能使用標(biāo)簽本身應(yīng)當(dāng)具備的能力(比如腳本執(zhí)行、樣式應(yīng)用等等)。
最常見的跨域問題是Ajax跨域訪問的問題,默認(rèn)情況下,跨域的URL是無法通過Ajax訪問的。這里我記錄我所了解到的跨域的方法:
1. 服務(wù)器端代理,這沒有什么可說的,缺點(diǎn)在于,默認(rèn)情況下接收Ajax請(qǐng)求的服務(wù)端是無法獲取到的客戶端的IP和UA的。
2. iframe,使用iframe其實(shí)相當(dāng)于開了一個(gè)新的網(wǎng)頁,具體跨域的方法大致是,域A打開的母頁面嵌套一個(gè)指向域B的iframe,然后提交數(shù)據(jù),完成之后,B的服務(wù)端可以:
●返回一個(gè)302重定向響應(yīng),把結(jié)果重新指回A域;
●在此iframe內(nèi)部再嵌套一個(gè)指向A域的iframe。
這兩者都最終實(shí)現(xiàn)了跨域的調(diào)用,這個(gè)方法功能上要比下面介紹到的JSONP更強(qiáng),因?yàn)榭缬蛲戤呏驞OM操作和互相之間的JavaScript調(diào)用都是沒有問題的,但是也有一些限制,比如結(jié)果要以URL參數(shù)傳遞,這就意味著在結(jié)果數(shù)據(jù)量很大的時(shí)候需要分割傳遞,甚是麻煩;還有一個(gè)麻煩是iframe本身帶來的,母頁面和iframe本身的交互本身就有安全性限制。
3. 利用script標(biāo)簽跨域,這個(gè)辦法也很常見,script標(biāo)簽是可以加載異域的JavaScript并執(zhí)行的,通過預(yù)先設(shè)定好的callback函數(shù)來實(shí)現(xiàn)和母頁面的交互。它有一個(gè)大名,叫做JSONP跨域,JSONP是JSON with Padding的略稱。它是一個(gè)非官方的協(xié)議,明明是加載script,為啥和JSON扯上關(guān)系呢?原來就是這個(gè)callback函數(shù),對(duì)它的使用有一個(gè)典型的方式,就是通過JSON來傳參,即將JSON數(shù)據(jù)填充進(jìn)回調(diào)函數(shù),這就是JSONP的JSON+Padding的含義。
在互聯(lián)網(wǎng)上有很多JSONP的服務(wù)來提供數(shù)據(jù),本質(zhì)上就是跨域請(qǐng)求,并且在請(qǐng)求URL中指定好callback,比如callback=result,那么在獲取到這些數(shù)據(jù)以后,就會(huì)自動(dòng)調(diào)用result函數(shù),并且把這些數(shù)據(jù)以JSON的形式傳進(jìn)去,例如(搜索“football”):
http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=football&callback=result
使用JQuery來調(diào)用就寫成:
$.getJSON("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=football&callback=?",function(data){
//...
});
總的來說,JSONP的跨域方式的局限性在于,只能使用GET請(qǐng)求,并且不能解決不同域的兩個(gè)頁面之間如何進(jìn)行JavaScript調(diào)用的問題。
4. Flash跨域:
它會(huì)訪問目標(biāo)網(wǎng)站根目錄下面的crossdomain.xml文件,根據(jù)文件中的內(nèi)容來確定是否允許此次跨域訪問:
<cross-domain-policy>
<allow-access-from domain="xxx.xxx.com" />
</cross-domain-policy>
5. img標(biāo)簽也可以使用,這也是一種非常常見的方法,功能上面弱一點(diǎn),只能發(fā)送一個(gè)get請(qǐng)求,沒有什么回調(diào),Google的點(diǎn)擊計(jì)數(shù)就是這樣確定的。
6. window.PostMessage,這個(gè)算是HTML5新加入的為跨域通訊考慮的機(jī)制,只有Firefox 3、Safari 4和IE8及之后的版本支持。使用它向其它窗口發(fā)送消息的調(diào)用方式如下:
otherWindow.postMessage(message, targetOrigin);
在接收的窗口,需要設(shè)置一個(gè)事件處理函數(shù)來接收發(fā)過來的消息:
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event){
if (event.origin !== "http://example.org:8080")
return;
}
注意這里必需要使用消息的origin和source屬性來驗(yàn)證發(fā)送者的身份,否則會(huì)造成XSS漏洞。
7. Access Control
有一些瀏覽器支持Access-Control-Allow-Origin這樣的響應(yīng)頭,比如:
header("Access-Control-Allow-Origin: http://www.a.com");
就指定了允許對(duì)www.a.com跨域訪問。
8. window.name
這個(gè)東西其實(shí)以前被用作黑客XSS的手段,其本質(zhì)是,當(dāng)window的location變化的時(shí)候,頁面會(huì)重新加載,但是有趣的是,這個(gè)window.name居然不發(fā)生變化,那么就可以用它來傳值了。配合iframe,改變幾次iframe的window對(duì)象,就完成了實(shí)用的跨域數(shù)據(jù)傳遞。
9. document.domain
這個(gè)方式適用于a.example.com和b.example.com這種跨域的通信,因?yàn)槎哂幸粋€(gè)共有的域,叫做example.com,只要設(shè)置document.domain為example.com就可以了,但是如果a.example1.com和b.example2.com之間要通信,它就沒辦法了。
10. Fragment Identitier Messaging(FIM)
這個(gè)方法很有意思,也需要iframe的配合。Fragment Identitier就是URL的井號(hào)(#)后面的經(jīng)常用于錨點(diǎn)定位的部分,這部分的改變不會(huì)導(dǎo)致頁面刷新,母窗口可以隨便訪問iframe的URL,而iframe也可以隨便訪問母窗口的URL,那這二者之間就可以通過改變Fragmement Identitier來實(shí)現(xiàn)通信了。缺點(diǎn)是Fragmement Identitier的改變會(huì)產(chǎn)生不必要的歷史記錄,而且也有長(zhǎng)度限制;另外,有的瀏覽器不支持onhashchange事件。
11. Cross Frame(CF)
這種方法是上述FIM方法的變種,CF和FIM的本質(zhì)其實(shí)在我的《GWT初體驗(yàn)》這篇文章里面都有介紹(只不過是被用來實(shí)現(xiàn)歷史和后退功能了),它會(huì)動(dòng)態(tài)創(chuàng)建一個(gè)不可見的iframe,指向異域,處理完以后,這個(gè)iframe的URL中的Fragment Identitier包含了處理結(jié)果,供母頁面訪問,而瀏覽器的URL沒有任何變化。
12. Cookie+P3P協(xié)議
利用P3P協(xié)議下跨域訪問Cookie的特性,來實(shí)現(xiàn)跨域訪問,也算一奇招。P3P是W3C公布的一項(xiàng)隱私保護(hù)推薦標(biāo)準(zhǔn),旨在為網(wǎng)上沖浪的Internet用戶提供隱私保護(hù)。把Cookie的path設(shè)置為“/”,即沒有任何域的限制,這個(gè)時(shí)候有的瀏覽器下面允許別的URL的頁面來讀取,有的則不允許,這種情況下需要在母頁面響應(yīng)的頭上面設(shè)置P3P的頭:
P3P: CP="CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR"
- AJAX javascript的跨域訪問執(zhí)行
- javascript使用window.name解決跨域問題
- Javascript 跨域訪問解決方案
- javascript跨域刷新實(shí)現(xiàn)代碼
- Javascript跨域請(qǐng)求的4種解決方式
- 使用JavaScript 實(shí)現(xiàn)各種跨域的方法
- javascript跨域的4種方法和原理詳解
- JavaScript使用HTML5的window.postMessage實(shí)現(xiàn)跨域通信例子
- JavaScript兩種跨域技術(shù)全面介紹
- 關(guān)于JavaScript跨域問題及實(shí)時(shí)刷新解決方案
- JavaScript中跨域調(diào)用Flash的方法
- JavaScript實(shí)現(xiàn)的雙向跨域插件分享
- javascript跨域原因以及解決方案分享
相關(guān)文章
JavaScript 選中文字并響應(yīng)獲取的實(shí)現(xiàn)代碼
當(dāng)鼠標(biāo)選擇一段文字時(shí),對(duì)這個(gè)事件產(chǎn)生響應(yīng),并且將選中的文字傳遞出去。2011-08-08JS 退出系統(tǒng)并跳轉(zhuǎn)到登錄界面的實(shí)現(xiàn)代碼
這篇文章介紹了退出系統(tǒng)后跳轉(zhuǎn)到登陸頁面的簡(jiǎn)單JS代碼,有需要的朋友可以參考一下2013-06-06JavaScript實(shí)現(xiàn)數(shù)組隨機(jī)排序的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)數(shù)組隨機(jī)排序的方法,涉及javascript數(shù)組遍歷與排序的相關(guān)技巧,需要的朋友可以參考下2015-06-06js實(shí)現(xiàn)登錄時(shí)記住密碼的方法分析
這篇文章主要介紹了js實(shí)現(xiàn)登錄時(shí)記住密碼的方法,結(jié)合實(shí)例形式分析了JavaScript基于cookie實(shí)現(xiàn)存儲(chǔ)登錄密碼相關(guān)操作技巧,需要的朋友可以參考下2020-04-04JS實(shí)現(xiàn)移動(dòng)端上下滑動(dòng)一次一屏
這篇文章主要為大家詳細(xì)介紹了JS實(shí)現(xiàn)移動(dòng)端上下滑動(dòng)一次一屏,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06js、jquery實(shí)現(xiàn)列表模糊搜索功能過程解析
這篇文章主要介紹了js、jquery實(shí)現(xiàn)列表模糊搜索功能過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03js實(shí)現(xiàn)文本框中焦點(diǎn)在最后位置
本篇文章主要是對(duì)js實(shí)現(xiàn)文本框中焦點(diǎn)在最后位置的示例代碼進(jìn)行了介紹,需要的朋友可以過來參考下,希望對(duì)大家有所 幫助2014-03-03