js中跨域方法

同源策略(協(xié)議+端口號+域名要相同)

1、jsonp跨域(只能解決get)

原理:動態(tài)創(chuàng)建一個script標簽。利用script標簽的src屬性不受同源策略限制,因為所有的src屬性和href屬性都不受同源策略的限制,可以請求第三方服務(wù)器資源內(nèi)容

步驟: 1).去創(chuàng)建一個script標簽

2).script的src屬性設(shè)置接口地址

3).接口參數(shù),必須要帶一個自定義函數(shù)名,要不然后臺無法返回數(shù)據(jù)

4).通過定義函數(shù)名去接受返回的數(shù)據(jù)

JSONP包含兩部分:回調(diào)函數(shù)和數(shù)據(jù)。?

回調(diào)函數(shù):當響應(yīng)到來時要放在當前頁面被調(diào)用的函數(shù)。?

數(shù)據(jù):就是傳入回調(diào)函數(shù)中的json數(shù)據(jù),也就是回調(diào)函數(shù)的參數(shù)了。

缺點:

#1)安全問題(請求代碼中可能存在安全隱患)

#2)要確定jsonp請求是否失敗并不容易

2、document.domain 基礎(chǔ)域名相同,子域名不同

瀏覽器同源策略限制:

#(1)不能通過ajax的方法去請求不同源中的文檔。

#(2)瀏覽器中不同域的框架之間是不能進行js的交互操作的。

? ? ? ?所以,在不同的框架之間(父子或同輩),是能夠獲取到彼此的window對象的,但不能使用獲取到的window對象的屬性和方法(html5中的postMessage方法是一個例外),總之,可以當做是只能獲取到一個幾乎無用的window對象。

? ? ? ?例如,在一個頁面 http:// www.example.com/a.html 中,有一個iframe框架它的src是http:// example.com/b.html, 很顯然,這個頁面與它里面的iframe框架是不同域的,所以是無法通過在頁面中書寫js代碼來獲取iframe中的東西的。所以我們就要用到document.domain

在頁面http:// www.a.com/dir/a.html中設(shè)置document.domain

<iframe src = "http://script.a.com/dir/b.html" id="iframe" onload = "loLoad()"></iframe>

<script>

document.domain = "a.com";//設(shè)置成主域

function test(){

? ? var iframe = document.getElementById("iframe");

? ? var win = iframe.contentWindow;

? ? //在這里就可以操作b.html

}

</script>

注意,document.domain的設(shè)置是有限制的:

只能把document.domain設(shè)置成自身或更高一級的父域,且主域必須相同。

例如:a.b.c.com 中某個文檔的document.domain 可以設(shè)成a.b.c.com、b.c.com 、c.com中的任意一個。


3、window.name 利用在一個瀏覽器窗口內(nèi),載入所有的域名都是共享一個window.name

? ? ? ?window的name屬性特征:name 值在不同的頁面(甚至不同域名)加載后依舊存在,并且可以支持非常長的 name 值(2MB),即在一個窗口(window)的生命周期內(nèi),窗口載入的所有的頁面都是共享一個window.name的,每個頁面window.name都有讀寫的權(quán)限。

正是由于window的name屬性的特征,所以可以使用window.name來進行跨域。

舉例:

1)在一個a.html頁面中,有如下代碼:

<script>

? ? window.name = "哈哈,我是頁面a設(shè)置的值喲!";

? ? //設(shè)置window.name的值

? ? setTimeout(function(){

? ? ? ? window.location = 'b.html';

? ? },3000);//3秒后把一個新頁面載入當前window

</script>

2)再在b.html中讀取window.name的值:

<script>

? ? alert(window.name);//讀取window.name的值

<script>

3)a.html載入3秒后,會跳轉(zhuǎn)到b.html頁面中

注意:

#1.window.name的值只能是字符串的形式,這個字符串的大小最大能允許2M左右甚至更大的一個容量,具體取決于不同的瀏覽器。

接下來使用window.name進行跨域舉例

比如:有一個example.com/a.html頁面,需要通過a.html頁面里的js來獲取另一個位于不同域上的頁面cnblogs.com/data.html里的數(shù)據(jù)。

1)創(chuàng)建cnblogs.com/data.html代碼:

<script>

? ? function getData(){

? ? //iframe載入data.html頁面會執(zhí)行此函數(shù)

? ? ? ? var ifr = document.getElementById("iframe");

? ? ? ? ifr.onload = function(){

? ? ? ? //這個時候iframe和a.html已經(jīng)處于同一源,可以互相訪問

? ? ? ? ? ? var data = ifr.contentWindow.name;

//獲取iframe中的window.name,也就是data.html中給它設(shè)置的數(shù)據(jù)

? ? ? ? ? ? alert(data);

? ? ? ? }

? ? ? ? ifr.src = 'b.html';//這里的b.html為隨便一個頁面,只要與a.html同源就行,目的是讓a.html能夠訪問到iframe中的東西,否則訪問不到

? ? }

</script>

<iframe id = "iframe" src = "cnblogs.com/data.html" style = "display:none" onload = "getData()"></iframe>

2)創(chuàng)建example.com/a.html的代碼:

<script>

? ? function getData(){

? ? //iframe載入data.html頁面會執(zhí)行此函數(shù)

? ? ? ? var ifr = document.getElementById("iframe");

? ? ? ? ifr.onload = function(){

? ? ? ? //這個時候iframe和a.html已經(jīng)處于同一源,可以互相訪問

? ? ? ? ? ? var data = ifr.contentWindow.name;

//獲取iframe中的window.name,也就是data.html中給它設(shè)置的數(shù)據(jù)

? ? ? ? ? ? alert(data);

? ? ? ? }

? ? ? ? ifr.src = 'b.html';//這里的b.html為隨便一個頁面,只要與a.html同源就行,目的是讓a.html能夠訪問到iframe中的東西,否則訪問不到

? ? }

</script>

<iframe id = "iframe" src = "cnblogs.com/data.html" style = "display:none" onload = "getData()"></iframe>

  想要即使a.html頁面不跳轉(zhuǎn)也能得到data.html里的數(shù)據(jù)。在a.html頁面中使用一個隱藏的iframe來充當一個中間人角色,由iframe去獲取data.html的數(shù)據(jù),然后a.html再去得到iframe獲取到的數(shù)據(jù)。

<script>

? ? function getData(){

? ? //iframe載入data.html頁面會執(zhí)行此函數(shù)

? ? ? ? var ifr = document.getElementById("iframe");

? ? ? ? ifr.onload = function(){

? ? ? ? //這個時候iframe和a.html已經(jīng)處于同一源,可以互相訪問

? ? ? ? ? ? var data = ifr.contentWindow.name;

//獲取iframe中的window.name,也就是data.html中給它設(shè)置的數(shù)據(jù)

? ? ? ? ? ? alert(data);

? ? ? ? }

? ? ? ? ifr.src = 'b.html';//這里的b.html為隨便一個頁面,只要與a.html同源就行,目的是讓a.html能夠訪問到iframe中的東西,否則訪問不到

? ? }

</script>

<iframe id = "iframe" src = "cnblogs.com/data.html" style = "display:none" onload = "getData()"></iframe>

4、使用跨域資源共享(CORS)來跨域

CORS:一種跨域訪問的機制,可以讓AJAX實現(xiàn)跨域訪問;CORS允許一個域上的網(wǎng)絡(luò)應(yīng)用向另一個域提交跨域AJAX請求。

原理:服務(wù)器設(shè)置Access-Control-Allow-Origin HTTP響應(yīng)頭之后,瀏覽器將會允許跨域請求.

就是使用自定義的HTTP頭部讓瀏覽器與服務(wù)器進行溝通,從而決定請求或響應(yīng)是應(yīng)該成功,還是應(yīng)該失敗。

1) IE中對CORS的實現(xiàn)是通過xdr

var xdr = new XDomainRequest();

xdr.onload = function(){

? ? console.log(xdr.responseText);

}

xdr.open('get', 'http://www.test.com');

......

xdr.send(null);

2) 其它瀏覽器中的實現(xiàn)就在xhr中

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = function () {

? if(xhr.readyState === 4 && xhr.status === 200){

? ? ? ? console.log(xhr.responseText);

? ? ? ? }

? ? }

}

xhr.open('get', 'http://www.test.com');

......

xhr.send(null);

3) 實現(xiàn)跨瀏覽器的CORS

function createCORS(method, url){

? ? var xhr = new XMLHttpRequest();

? ? if('withCredentials' in xhr){

? ? ? ? xhr.open(method, url, true);

? ? }else if(typeof XDomainRequest != 'undefined'){

? ? ? ? var xhr = new XDomainRequest();

? ? ? ? xhr.open(method, url);

? ? }else{

? ? ? ? xhr = null;

? ? }

? ? return xhr;

}

var request = createCORS('get', 'http://www.test.com');

if(request){

? ? request.onload = function(){

? ? ? ? ......

? ? };

? ? request.send();

}

5、利用h5新特性window.postMessage()

window.postMessage(message,targetOrigin) 方法是html5新引進的特性,可以使用它來向其它的window對象發(fā)送消息,無論這個window對象是屬于同源或不同源(可實現(xiàn)跨域),目前IE8+、FireFox、Chrome、Opera等瀏覽器都已經(jīng)支持window.postMessage方法。

message:為要發(fā)送的消息,類型只能為字符串;

targetOrigin:用來限定接收消息的那個window對象所在的域,如果不想限定域,可以使用通配符 “*”。

1)創(chuàng)建www.test.com/a.html頁面代碼:

<script>

function onLoad(){

? ? var iframe = document.getElementById("iframe");

? ? var win = iframe.contentWindow;

? ? win.postMessage('哈哈,我是來自頁面a.html的信息喲!','*');//向不同域的www.script.com/b.html發(fā)送消息

}

</script>

<iframe id="iframe" src="www.script.com/b.html" onload="onLoad()"></iframe>

2)創(chuàng)建www.script.com/b.html頁面代碼:

<script>

window.onmessage = function (e) {

e = e || event ;

alert (e.data);

}

</script>

優(yōu)點:使用postMessage來跨域傳送數(shù)據(jù)還是比較直觀和方便的;?

缺點:?IE6、IE7不支持,所以用不用還得根據(jù)實際需要來決定。




?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Section1、為什么要跨域? 自古以來(1995年起),為了用戶的信息安全,瀏覽器就引入了同源策略。那么同源策...
    qhaobaba閱讀 471評論 0 0
  • 原文連接:http://www.cnblogs.com/2050/p/3191744.html js中幾種實用的跨...
    小豆soybean閱讀 405評論 0 3
  • 個人轉(zhuǎn)載做筆記用 http://web.jobbole.com/88525/ 這里說的js跨域是指通過js在不同的...
    平謙閱讀 443評論 0 7
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實際上跨域的范圍絕對不止那么狹隘。具體概念如下:只要協(xié)議...
    w_zhuan閱讀 622評論 0 0
  • 漸變的面目拼圖要我怎么拼? 我是疲乏了還是投降了? 不是不允許自己墜落, 我沒有滴水不進的保護膜。 就是害怕變得面...
    悶熱當乘涼閱讀 4,491評論 0 13

友情鏈接更多精彩內(nèi)容