摘要:通過(guò)跨域通過(guò)引入的不受同源策略的限制,所以我們可以通過(guò)標(biāo)簽引入一個(gè)或者是一個(gè)其他后綴形式如,等的文件,此文件返回一個(gè)函數(shù)的調(diào)用。
1.跨域的定義
只要協(xié)議、域名、端口有任何一個(gè)不同,就會(huì)被當(dāng)做為不同的域,如果從A域名訪問(wèn)B域名上的資源就叫做跨域。
下面我們來(lái)看下幾種跨域的方法:
2.document.domain瀏覽器的同源策略有一些限制,第一,不能通過(guò)ajax方法去請(qǐng)求不同源的資源;第二,瀏覽器中不同域的框架之間是不能進(jìn)行JS交互的。假如有一個(gè)頁(yè)面A,地址是http://www.domain.cn/A.html,在這個(gè)頁(yè)面里有個(gè)iframe,它的地址是http://domain.cn/B.html,顯然A和B是不同域的,所以我們沒(méi)法通過(guò)JS來(lái)訪問(wèn)iframe中的數(shù)據(jù)和方法。
這種情況就就可以用document.domain來(lái)解決。
解決方法就是把http://www.domain.cn/A.html和http://domain.cn/B.html的document.domain設(shè)成相同的域名,需要注意的是, 我們只能把document.domain設(shè)置成自身或更高一級(jí)的父域,且主域必須相同。
在A中我們把設(shè)置document.domain:
在B頁(yè)面中我們也設(shè)置document.domain
但是這種方法只適合不同子域的框架間的交互。
3.location.hash在一個(gè)有iframe的頁(yè)面中,父窗口可以對(duì)iframe的URL進(jìn)行讀寫(xiě),iframe也可以讀寫(xiě)父窗口的URL。URL有一部分#加上后面的字符可以用來(lái)進(jìn)行錨點(diǎn)定位,這部分就是hash。利用修改URL的hash部分可以進(jìn)行雙向通信,從而達(dá)到跨域的目的。每個(gè)window通過(guò)改變其他window的location來(lái)發(fā)送消息,其他窗口通過(guò)監(jiān)聽(tīng)URL變化的事件來(lái)接收消息。這個(gè)方式的通信會(huì)造成一些不必要的瀏覽器歷史記錄,而且有些瀏覽器不支持onhashchange事件,需要輪詢來(lái)獲知URL的改變,最后,這樣做也存在缺點(diǎn),諸如數(shù)據(jù)直接暴露在了url中,數(shù)據(jù)容量和類型都有限等。下面是一個(gè)例子:
假如父頁(yè)面是baidu.com/a.html,iframe嵌入的頁(yè)面為google.com/b.html(此處省略了域名等url屬性),要實(shí)現(xiàn)此兩個(gè)頁(yè)面間的通信可以通過(guò)以下方法。
a.html傳送數(shù)據(jù)到b.html,a.html下修改iframe的src為:
google.com/b.html#paco
b.html監(jiān)聽(tīng)到url發(fā)生變化,觸發(fā)相應(yīng)操作
b.html傳送數(shù)據(jù)到a.html,由于兩個(gè)頁(yè)面不在同一個(gè)域下IE、Chrome不允許修改parent.location.hash的值,所以要借助于父窗口域名下的一個(gè)代理iframe
b.html下創(chuàng)建一個(gè)隱藏的iframe,此iframe的src是baidu.com域下的,并掛上要傳送的hash數(shù)據(jù),如src=”http://www.baidu.com/proxy.ht...”
proxy.html監(jiān)聽(tīng)到url發(fā)生變化,修改a.html的url(因?yàn)閍.html和proxy.html同域,所以proxy.html可修改a.html的url hash)
a.html監(jiān)聽(tīng)到url發(fā)生變化,觸發(fā)相應(yīng)操作
b.html的代碼:
try { parent.location.hash = "data"; } catch (e) { // ie、chrome的安全機(jī)制無(wú)法修改parent.location.hash, var ifrproxy = document.createElement("iframe"); ifrproxy.style.display = "none"; ifrproxy.src = "http://www.baidu.com/proxy.html#data"; document.body.appendChild(ifrproxy); }
proxy.html頁(yè)面的關(guān)鍵代碼如下 :
//因?yàn)閜arent.parent(即baidu.com/a.html)和baidu.com/proxy.html屬于同一個(gè)域,所以可以改變其location.hash的值 parent.parent.location.hash = self.location.hash.substring(1);4.通過(guò)H5的postMessage()
IE8、Chrome、Firefox、Safari、Opera等瀏覽器都支持這個(gè)方法,這個(gè)功能主要包括接收信息的方法和發(fā)送消息的postMessage方法。比如damonare.cn域的A頁(yè)面通過(guò)iframe嵌入了一個(gè)google.com域的B頁(yè)面,可以通過(guò)以下方法實(shí)現(xiàn)A和B的通信:
A頁(yè)面通過(guò)postMessage發(fā)送消息:
window.onload = function() { var ifr = document.getElementById("ifr"); var targetOrigin = "http://www.google.com"; ifr.contentWindow.postMessage("hello world!", targetOrigin); }
B頁(yè)面通過(guò)message事件監(jiān)聽(tīng)并接受消息:
var onmessage = function (event) { var data = event.data;//消息 var origin = event.origin;//消息來(lái)源地址 var source = event.source;//源Window對(duì)象 if(origin=="http://www.baidu.com"){ console.log(data);//hello world! } }; if (typeof window.addEventListener != "undefined") { window.addEventListener("message", onmessage, false); } else if (typeof window.attachEvent != "undefined") { //for ie window.attachEvent("onmessage", onmessage); }
上面幾種方式都是頁(yè)面和iframe之間或者頁(yè)面和頁(yè)面之間的,下面介紹的是單向跨域,一般用于獲取數(shù)據(jù)。
5.通過(guò)JSOP跨域通過(guò)script引入的JS不受同源策略的限制,所以我們可以通過(guò)script標(biāo)簽引入一個(gè)js或者是一個(gè)其他后綴形式(如php,jsp等)的文件,此文件返回一個(gè)js函數(shù)的調(diào)用。
比如,有個(gè)a.html頁(yè)面,它里面的代碼需要利用ajax獲取一個(gè)不同域上的json數(shù)據(jù),假設(shè)這個(gè)json數(shù)據(jù)地址是http://damonare.cn/data.php,那么a.html中的代碼就可以這樣:
因?yàn)槭钱?dāng)做一個(gè)js文件來(lái)引入的,所以http://damonare.cn/data.php返回的必須是一個(gè)能執(zhí)行的js文件,所以這個(gè)頁(yè)面的php代碼可能是這樣的,這需要和后端約定好:
最終,輸出結(jié)果為:dosomething([‘a(chǎn)’,’b’,’c’]);
使用jQuery封裝的JSONP方法可以很方便的進(jìn)行jsonp請(qǐng)求:
jquery會(huì)自動(dòng)生成一個(gè)全局函數(shù)來(lái)替換callback=?中的問(wèn)號(hào),之后獲取到數(shù)據(jù)后又會(huì)自動(dòng)銷毀,實(shí)際上就是起一個(gè)臨時(shí)代理函數(shù)的作用。$.getJSON方法會(huì)自動(dòng)判斷是否跨域,不跨域的話,就調(diào)用普通的ajax方法;跨域的話,則會(huì)以異步加載js文件的形式來(lái)調(diào)用jsonp的回調(diào)函數(shù)。
優(yōu)點(diǎn):不受到同源策略的影響,兼容性好,在一些古老的瀏覽器里也可以運(yùn)行,不需要XMLHttpRequest或ActiveX的支持;并且在請(qǐng)求完畢后可以通過(guò)調(diào)用callback的方式回傳結(jié)果。
缺點(diǎn):只支持GET請(qǐng)求,不能解決不同域的兩個(gè)頁(yè)面之間如何進(jìn)行JavaScript調(diào)用的問(wèn)題。
6. 通過(guò)CORS跨域CORS(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問(wèn)跨域資源時(shí),瀏覽器與服務(wù)器應(yīng)該如何溝通。CORS背后的基本思想就是使用自定義的HTTP頭部讓瀏覽器與服務(wù)器進(jìn)行溝通,從而決定請(qǐng)求或響應(yīng)是應(yīng)該成功還是失敗。目前,所有瀏覽器都支持該功能,IE瀏覽器不能低于IE10。
因此,實(shí)現(xiàn)CORS通信的關(guān)鍵是服務(wù)器。只要服務(wù)器實(shí)現(xiàn)了CORS接口,就可以跨源通信。
服務(wù)器端對(duì)于CORS的支持,主要就是通過(guò)設(shè)置Access-Control-Allow-Origin來(lái)進(jìn)行的。如果瀏覽器檢測(cè)到相應(yīng)的設(shè)置,就可以允許Ajax進(jìn)行跨域的訪問(wèn)。
CORS與JSONP的對(duì)比:
JSONP只能實(shí)現(xiàn)GET請(qǐng)求,而CORS支持所有類型的HTTP請(qǐng)求;
使用CORS,開(kāi)發(fā)者可以使用普通的XMLHttpRequest發(fā)起請(qǐng)求和獲得數(shù)據(jù),比起JSONP有
更好的錯(cuò)誤處理。
CORS與JSONP相比,無(wú)疑更為先進(jìn)、方便和可靠。
7.window.namewindow對(duì)象有個(gè)name屬性,該屬性有個(gè)特征:即在一個(gè)窗口(window)的生命周期內(nèi),窗口載入的所有的頁(yè)面都是共享一個(gè)window.name的,每個(gè)頁(yè)面對(duì)window.name都有讀寫(xiě)的權(quán)限,window.name是持久存在一個(gè)窗口載入過(guò)的所有頁(yè)面中的,并不會(huì)因新頁(yè)面的載入而進(jìn)行重置。
比如:我們?cè)谌我庖粋€(gè)頁(yè)面輸入
window.name = "My window"s name"; setTimeout(function(){ window.location.; },1000)
進(jìn)入damonare.cn頁(yè)面后我們?cè)贆z測(cè)再檢測(cè) window.name :
window.name; // My window"s name
由于安全原因,瀏覽器始終會(huì)保持 window.name 是string 類型。
這種方法與 document.domain 方法相比,放寬了域名后綴要相同的限制,可以從任意頁(yè)面獲取 string 類型的數(shù)據(jù)。
8.反向代理服務(wù)器基礎(chǔ)思想很簡(jiǎn)單,將你的服務(wù)器配置成需要 跨域獲取的資源 的反向代理服務(wù)器。
我們只需要配置nginx,在一個(gè)服務(wù)器上配置多個(gè)前綴來(lái)轉(zhuǎn)發(fā)http/https請(qǐng)求到多個(gè)真實(shí)的服務(wù)器即可。這樣,這個(gè)服務(wù)器上所有url都是相同的域名、協(xié)議和端口。因此,對(duì)于瀏覽器來(lái)說(shuō),這些url都是同源的,沒(méi)有跨域限制。而實(shí)際上,這些url實(shí)際上由物理服務(wù)器提供服務(wù)。這些服務(wù)器內(nèi)的javascript可以跨域調(diào)用所有這些服務(wù)器上的url。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/51148.html
摘要:前言騰訊一面,相比阿里一面來(lái)說(shuō),騰訊一面先給打電話預(yù)定時(shí)間,這也給了我們這些面試者去準(zhǔn)備的時(shí)間。其實(shí)閉包也就是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域的函數(shù)而已。常用的創(chuàng)建閉包的方法就是在函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。 前言 騰訊一面,相比阿里一面來(lái)說(shuō),騰訊一面先給打電話預(yù)定時(shí)間,這也給了我們這些面試者去準(zhǔn)備的時(shí)間。但是也正是因?yàn)檫@種確定性,也有在等待電話的時(shí)候的心情的忐忑。 背景 我是一名大三學(xué)生,大一...
摘要:所謂同源是指協(xié)議域名端口三者相同,即便兩個(gè)不同的域名指向同一個(gè)地址,也非同源。那么怎樣解決跨域問(wèn)題的呢通過(guò)跨域跨域跨域跨域跨域資源共享代理跨域中間件代理跨域音樂(lè)教程老師有用到協(xié)議跨域后端在頭部信息里面設(shè)置安全域名公司后端給解決過(guò)持續(xù)更新中 JavaScript篇 如何獲取瀏覽器URL中查詢字符串中的參數(shù)? 1.封裝方法 getUrlArgs(url) { const args =...
摘要:所謂同源是指協(xié)議域名端口三者相同,即便兩個(gè)不同的域名指向同一個(gè)地址,也非同源。那么怎樣解決跨域問(wèn)題的呢通過(guò)跨域跨域跨域跨域跨域資源共享代理跨域中間件代理跨域音樂(lè)教程老師有用到協(xié)議跨域后端在頭部信息里面設(shè)置安全域名公司后端給解決過(guò)持續(xù)更新中 JavaScript篇 如何獲取瀏覽器URL中查詢字符串中的參數(shù)? 1.封裝方法 getUrlArgs(url) { const args =...
摘要:是的,方法被調(diào)用時(shí),會(huì)在所有頁(yè)面腳本執(zhí)行完畢之后向目標(biāo)窗口派發(fā)一個(gè)消息。該消息有四個(gè)屬性需要注意屬性表示該的類型屬性為的第一個(gè)參數(shù)屬性表示調(diào)用方法時(shí)調(diào)用頁(yè)面的當(dāng)前狀態(tài)屬性記錄調(diào)用方法的窗口信息。 1.為什么要跨域 同源策略限制一個(gè)源加載的文檔或文檔與來(lái)自另一個(gè)源的資源進(jìn)行交互。這是一個(gè)用于隔離潛在惡意文件的安全機(jī)制。什么是同源呢? 如果協(xié)議,端口(如果指定了一個(gè))和域名對(duì)于兩個(gè)頁(yè)面是相...
摘要:跨域正確的打開(kāi)方式經(jīng)過(guò)對(duì)同源策略的了解,我們應(yīng)該要消除對(duì)瀏覽器的誤解,同源策略是瀏覽器做的一件好事,是用來(lái)防御來(lái)自邪門(mén)歪道的攻擊,但總不能為了不讓壞人進(jìn)門(mén)而把全部人都拒之門(mén)外吧。 跨域這兩個(gè)字就像一塊狗皮膏藥一樣黏在每一個(gè)前端開(kāi)發(fā)者身上,無(wú)論你在工作上或者面試中無(wú)可避免會(huì)遇到這個(gè)問(wèn)題。為了應(yīng)付面試,我每次都隨便背幾個(gè)方案,也不知道為什么要這樣干,反正面完就可以扔了,我想工作上也不會(huì)用到...
閱讀 3994·2021-09-22 16:03
閱讀 5345·2021-09-22 15:40
閱讀 1199·2021-09-06 15:02
閱讀 879·2019-08-30 15:53
閱讀 2232·2019-08-29 15:35
閱讀 1117·2019-08-23 18:22
閱讀 3346·2019-08-23 16:06
閱讀 652·2019-08-23 12:27