// 使用通配符 * ,表示当前服务端响应任何域名发起请求,不推荐 可以具体指定某个地址
<?php header('Access-Control-Allow-Origin:*'); ?>
就这样在服务端简单加一句响应头responese headers声明,一个跨域请求就不会被浏览器的同源安全策略所阻止了!
在浏览器端通过XHR对象(IE的XDomainRequest对象),实现ajax跨域:
function corsReq(){
if(window.XMLHttpRequest)
var xhr = new XMLHttpRequest();
else if(window.XDomainRequest){
var xhr = new XDomainRequest();
}
xhr.open('POST',url,true); //url使用绝对路径 xhr.send(data); xhr.close(); ..... }
浏览器检测头信息,在响应头信息中,header中包含了 Access-Control-Allow-Origin这个字段,如果字段值和我们域名相同,浏览器才会使用里面的数据做下一步处理。
(只有当目标页面的response中,包含了 Access-Control-Allow-Origin
这个header,并且它的值里有我们自己的域名时,浏览器才允许我们拿到它页面的数据进行下一步处理。)
缺点:IE10以上才支持,IE 8 ie 9通过XDomainRequest支持
1、JSON-P跨域
什么事jsonp?
利用在页面中创建<script>节点的方法向不同域提交HTTP请求的方法称为JSONP
动态脚本注入的方法,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的
var eleScript= document.createElement("script"); eleScript.type = "text/javascript"; eleScript.src = "http://example2.com/getinfo.php"; document.getElementsByTagName("HEAD")[0].appendChild(eleScript);
2、window.name跨域
indow对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。
数据大小有限制,大小一般为2M,IE和firefox下可以大至32M左右
有三个页面:
a.com/app.html:应用页面。
a.com/proxy.html:代理文件,一般是一个没有任何内容的html文件,需要和应用页面在同一域下。
b.com/data.html:应用页面需要获取数据的页面,可称为数据页面。
实现起来基本步骤如下:
在应用页面(a.com/app.html)中创建一个iframe,把其src指向数据页面(b.com/data.html)。
数据页面会把数据附加到这个iframe的window.name上,data.html代码如下:
1 <script type="text/javascript"> 2 3 window.name = 'I was there!'; // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右 4 5 // 数据格式可以自定义,如json、字符串 6 7 </script>
在应用页面(a.com/app.html)中监听iframe的onload事件,在此事件中设置这个iframe的src指向本地域的代理文件(代理文件和应用页面在同一域下,所以可以相互通信)。app.html部分代码如下:
-
<iframe src="http://gisbar.net/beta/d.html" style='display:none' frameborder="0" id="dataPage" onload ='loadFrame()'></iframe>
<script type="text/javascript">
function loadFrame(){
var dataIframe = document.getElementById('dataPage');
dataIframe.onload = function (){
var data = dataIframe.contentWindow.name;
console.log('window.name 跨域请求的数据:',data);
}
dataIframe.src = 'http://a.com/proxy.html';}
</script>
获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)。
<script type="text/javascript"> iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe); </script>
总结起来即:iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
引自:http://www.cnblogs.com/rainman/archive/2011/02/21/1960044.html
3、HTML5中新引进的window.postMessage方法跨域
window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。
调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。
缺点是IE6、IE7不支持
<iframe src="http://gisbar.net/beta/d.html" style='display:block' frameborder="1" id="msgFrame" onload ='loadMsgFrame()'></iframe>
//postMessage跨域 function loadMsgFrame(){ var msgFrame = document.getElementById('msgFrame'); msgFrame.contentWindow.postMessage('来自localhost的数据','http://gisbar.net/beta/'); //发送给指定域下的页面 }
在http://gisbar.net/beta/d.html跨域页面中:
window.onmessage = function(e){ console.log('e',e); alert(e.data); //来自localhost的数据
}
4、iframe+document.domain来跨子域
我们只要把http://www.example.com/a.html 和 http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。