跨域方法的整理

来源:互联网 发布:路由器怎么网络慢 编辑:程序博客网 时间:2024/06/05 07:59

function demo(){   console.log(data.msg)}

前端程序员不可避免的会遇到跨域这个问题,而随着时间的推移,解决跨域问题的方法也是日渐丰富。于是我就稍作整理,来完善自己的知识体系,如恰好也能帮你解决一些问题,那我将非常高兴。


方法一:jsonp

假设,我们源页面是在a.com,想要获取b.com的数据,我们可以动态插入来源于b.com的脚本:

script = document.createElement('script');script.type='text/javascript';script.src = 'http://www.b.com/getdata?callback=demo'
这里,我们利用动态脚本的src属性变相的发送了一个http://www.b.com/getdata?callback=demo的GET请求。这个时候,b.com页面接收到这个请求时,如果没有JSONP,会正常返回json的数据结果,像这样:

{msg:‘helloworld’}

而利用JSONP,服务端会接受这个callback参数,然后利用这个参数包装要返回的数据:

这个时候,如果a.com的页面上敲好有demo的函数:

function demo(data){console.log(data.msg)};

当远程数据一返回的时候,随着动态脚本的执行,这个demo函数就会被执行。



方法二:$.getJSON

   $.getJSON('http://www.b.com/getdata?callback=?',function(data){console.log(data.msg)})

方法三:$.ajax

                这种方法,只要指定dataType为jsonp即可

$.ajax({

url:'http://www.b.com/getdata?callback=?',

dataType:'jsonp',

jsonpCallback:'demo',

success:function(data){

console.log(data.msg);

}

})

缺陷:1.没有关于JSONP调用的错误处理,一旦回调函数调用失败,浏览器会以静默失败的方式处理。

     2.它只支持GET请求,这是该技术本身的特性所决定的。

方法四:document.domian

域名与子域名之间也同样受同源策略的限制,因此当域名与子域名需要通信时,我们可以如下操作:

    document.domain ='a.com';
var iframe = document.createElement('iframe');
iframe.src = 'http://document.a.com';
iframe.style.display= "none";
document.body.appendChild(iframe);
iframe.onload = function(){
var targetDocument = iframe.contentDocument||iframe.contentWindow.document;
}
        方法五:

window.name这个全局属性主要是用来获取和设置窗口名称的,但是通过结合iframe也可以跨域获取数据。我们知道,每个iframe都有包裹它的window对象,所以window。name属性就可以被共享。

例子:

var  iframe = document.createElement('iframe');

var canGetData = false;

//监听事件

iframe.onload = function(){

if(!canGetData){

iframe.src = 'http://www.a.com';

canGetData = true;

}else{

var data = iframe.contentWindow.name;

//获取数据后取出iframe,防止不断刷新

iframe.contentWindow.close();

document.body.removeChild(iframe);


}

}

iframe.src = 'http://www.b.com/getdata.html'

iframe.style.display = 'none';

document.body.appendChild(iframe);

b.com/getdata.html中存放的数据需要存储在window。name属性中:

<script>

var  data = {msg:'hello,world'};

window.name = JSON.stringify(data);

</script>


方法六:window.postMessage(重点推荐) 跨文档消息

用postMessage的特性可以实现为安全可信的跨域通信

postMessage是HTML5新增在window对象上的方法,目的是为了解决在父子页面上通信的问题。该技术有个专有名词:跨文档消息(cross-document messaging)。利用postMessage的特性可以实现较为安全可信的跨域通信。


postMessage方法接受两个参数:


message: 要传递的对象,只支持字符串信息,因此如果需要发送对象,可以使用JSON.stringify和JSON.parse做处理

targetOrigin: 目标域,需要注意的是协议,端口和主机名必须与要发送的消息的窗口一致。如果不想限定域,可以使用通配符“*”,但是从安全上考虑,不推荐这样做。


下面介绍一个例子:

首先,先创建一个demo的html文件,我们这里采用的是iframe的跨域,当然也可以跨窗口。


<p> <button id="sendMsg">sendMsg</button> </p>

<iframe id="receiveMsg" src="http://b.html"> </iframe>


然后,在sendMsg的按钮上绑定点击事件,触发postMessage方法来发送信息给iframe:


window.onload = function() { var receiveMsg = document.getElementById('receiveMsg').contentWindow;

//获取在iframe中显示的窗口

  var sendBtn = document.getElementById('sendMsg');

sendBtn.addEventListener('click', function(e) {

e.preventDefault(); receiveMsg.postMessage('Hello world', 'http://b.html');

});

}


接着,你需要在iframe的绑定的页面源中监听message事件就能正常获取消息了。其中,MessageEvent对象有三个重要属性:data用于获取数据,source用于获取发送消息的窗口对象,origin用于获取发送消息的源。


window.onload = function() {

var messageBox = document.getElementById('messageBox');

window.addEventListener('message', function(e) {

//do something //考虑安全性,需要判断一下信息来源

if(e.origin !== 'http://xxxx') return;

messageBox.innerHTML = e.data;

});

}


总得来说,postMessage的使用十分简单,在处理一些和多页面通信、页面与iframe等消息通信的跨域问题时,有着很好的适用性。

七:服务器跨域

八:CORS(跨域资源共享)