詳解JavaScript跨域總結(jié)與解決辦法
什么是跨域
JavaScript出于安全方面的考慮,不允許跨域調(diào)用其他頁面的對象。但在安全限制的同時(shí)也給注入iframe或是ajax應(yīng)用上帶來了不少麻煩。這里把涉及到跨域的一些問題簡單地整理一下:
首先什么是跨域,簡單地理解就是因?yàn)镴avaScript同源策略的限制,a.com 域名下的js無法操作b.com或是c.a.com域名下的對象。更詳細(xì)的說明可以看下表:
URL | 說明 | 是否允許通信 |
---|---|---|
http://www.a.com/a.js http://www.a.com/b.js |
同一域名下 | 允許 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同一域名下不同文件夾 | 允許 |
http://www.a.com:8000/a.js http://www.a.com/b.js |
同一域名,不同端口 | 不允許 |
http://www.a.com/a.js https://www.a.com/b.js |
同一域名,不同協(xié)議 | 不允許 |
http://www.a.com/a.js http://70.32.92.74/b.js |
域名和域名對應(yīng)ip | 不允許 |
http://www.a.com/a.js http://script.a.com/b.js |
主域相同,子域不同 | 不允許 |
http://www.a.com/a.js http://a.com/b.js |
同一域名,不同二級(jí)域名(同上) | 不允許(cookie這種情況下也不允許訪問) |
http://www.cnblogs.com/a.js http://www.a.com/b.js |
不同域名 | 不允許 |
特別注意兩點(diǎn):
第一,如果是協(xié)議和端口造成的跨域問題“前臺(tái)”是無能為力的,
第二:在跨域問題上,域僅僅是通過“URL的首部”來識(shí)別而不會(huì)去嘗試判斷相同的ip地址對應(yīng)著兩個(gè)域或兩個(gè)域是否在同一個(gè)ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解為“Domains, protocols and ports must match”。
接下來簡單地總結(jié)一下在“前臺(tái)”一般處理跨域的辦法,后臺(tái)proxy這種方案牽涉到后臺(tái)配置,這里就不闡述了。
1、document.domain+iframe的設(shè)置
對于主域相同而子域不同的例子,可以通過設(shè)置document.domain的辦法來解決。 具體的做法是可以在http://www.a.com/a.html和http://script.a.com/b.html兩個(gè)文件中分別加上 document.domain = ‘a(chǎn).com';然后通過a.html文件中創(chuàng)建一個(gè)iframe,去控制iframe的contentDocument,這樣兩個(gè)js文件之間就可以 “交互”了。當(dāng)然這種辦法只能解決主域相同而二級(jí)域名不同的情況,如果你異想天開的把script.a.com的domian設(shè)為alibaba.com 那顯然是會(huì)報(bào)錯(cuò)地!代碼如下:
www.a.com上的a.html
document.domain = 'a.com'; var ifr = document.createElement('iframe'); ifr.src = 'http://script.a.com/b.html'; ifr.style.display = 'none'; document.body.appendChild(ifr); ifr.onload = function(){ var doc = ifr.contentDocument || ifr.contentWindow.document; // 在這里操縱b.html alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue); };
script.a.com上的b.html
document.domain = 'a.com';
這種方式適用于{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何頁面相互通信。
備注:某一頁面的domain默認(rèn)等于window.location.hostname。主域名是不帶www的域名,例如a.com,主域名前面帶前綴的通常都為二級(jí)域名或多級(jí)域名,例如www.a.com其實(shí)是二級(jí)域名。 domain只能設(shè)置為主域名,不可以在b.a.com中將domain設(shè)置為c.a.com。
問題:
1、安全性,當(dāng)一個(gè)站點(diǎn)(b.a.com)被攻擊后,另一個(gè)站點(diǎn)(c.a.com)會(huì)引起安全漏洞。
2、如果一個(gè)頁面中引入多個(gè)iframe,要想能夠操作所有iframe,必須都得設(shè)置相同domain。
2、動(dòng)態(tài)創(chuàng)建script
雖然瀏覽器默認(rèn)禁止了跨域訪問,但并不禁止在頁面中引用其他域的JS文件,并可以自由執(zhí)行引入的JS文件中的function(包括操作cookie、Dom等等)。根據(jù)這一點(diǎn),可以方便地通過創(chuàng)建script節(jié)點(diǎn)的方法來實(shí)現(xiàn)完全跨域的通信。具體的做法可以參考YUI的Get Utility
這里判斷script節(jié)點(diǎn)加載完畢還是蠻有意思的:ie只能通過script的readystatechange屬性,其它瀏覽器是script的load事件。以下是部分判斷script加載完畢的方法。
js.onload = js.onreadystatechange = function() { if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') { // callback在此處執(zhí)行 js.onload = js.onreadystatechange = null; } };
3、利用iframe和location.hash
相關(guān)文章
jszip插件實(shí)現(xiàn)圖片打包下載的方法分析
這篇文章主要介紹了jszip插件實(shí)現(xiàn)圖片打包下載的方法,結(jié)合實(shí)例形式分析了JavaScript使用jszip插件依據(jù)圖片列表打包下載zip壓縮文件的相關(guān)操作技巧,需要的朋友可以參考下2023-05-05JavaScript實(shí)踐之使用Canvas開發(fā)一個(gè)可配置的大轉(zhuǎn)盤抽獎(jiǎng)功能
公司項(xiàng)目搞優(yōu)惠活動(dòng),讓做一個(gè)轉(zhuǎn)盤抽獎(jiǎng)的活動(dòng),這篇文章主要給大家介紹了關(guān)于JavaScript實(shí)踐之使用Canvas開發(fā)一個(gè)可配置的大轉(zhuǎn)盤抽獎(jiǎng)功能的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11前端 javascript 實(shí)現(xiàn)文件下載的示例
這篇文章主要介紹了前端 javascript 實(shí)現(xiàn)文件下載的示例2020-11-11