什么是跨域?
观点:只需协定、域名、端口有任何一个差别,都被看成是差别的域。
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 统一域名,差别协定 不许可
http://www.a.com/a.js
http://70.32.92.74/b.js 域名和域名对应ip 不许可
http://www.a.com/a.js
http://script.a.com/b.js 主域雷同,子域差别 不许可
http://www.a.com/a.js
http://a.com/b.js 统一域名,差别二级域名(同上) 不许可(cookie这类状况下也不许可接见)
http://www.cnblogs.com/a.js
http://www.a.com/b.js 差别域名 不许可
关于端口和协定的差别,只能经由过程背景来处置惩罚。
跨域资本同享(CORS)
CORS(Cross-Origin Resource Sharing
)跨域资本同享,定义了必需在接见跨域资本时,浏览器与服务器应当怎样沟通。CORS
背地的基本思想就是运用自定义的HTTP头部让浏览器与服务器举行沟通,从而决议要求或相应是应当胜利照样失利。
<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.open("GET", "/trigkit4",true);
xhr.send();
</script>
以上的trigkit4
是相对路径,假如我们要运用CORS
,相干Ajax
代码能够以下所示:
<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://segmentfault.com/u/trigkit4/",true);
xhr.send();
</script>
代码与之前的区分就在于相对路径换成了其他域的绝对路径,也就是你要跨域接见的接口地点。
服务器端关于CORS
的支撑,重要就是经由过程设置Access-Control-Allow-Origin
来举行的。假如浏览器检测到相应的设置,就可以够许可Ajax举行跨域的接见。
要处置惩罚跨域的题目,我们能够运用以下几种要领:
经由过程jsonp跨域
如今题目来了?什么是jsonp
?维基百科的定义是:JSONP(JSON with Padding)
是材料花样 JSON
的一种“运用情势”,能够让网页从别的网域要材料。
JSONP
也叫添补式JSON,是运用JSON的一种新要领,只不过是被包含在函数挪用中的JSON,比方:
callback({"name","trigkit4"});
JSONP由两部分构成:回调函数和数据。回调函数是当相应到来时应当在页面中挪用的函数,而数据就是传入回调函数中的JSON数据。
在js中,我们直接用XMLHttpRequest
要求差别域上的数据时,是不能够的。然则,在页面上引入差别域上的js剧本文件倒是能够的,jsonp恰是应用这个特性来完成的。 比方:
<script type="text/javascript">
function dosomething(jsondata){
//处置惩罚获得的json数据
}
</script>
<script src="http://example.com/data.php?callback=dosomething"></script>
js文件载入胜利后会实行我们在url参数中指定的函数,而且会把我们须要的json数据作为参数传入。所以jsonp是须要服务器端的页面举行相应的合营的。
<?php
$callback = $_GET['callback'];//获得回调函数名
$data = array('a','b','c');//要返回的数据
echo $callback.'('.json_encode($data).')';//输出
?>
终究,输出效果为:dosomething(['a','b','c']);
假如你的页面运用jquery,那末经由过程它封装的要领就可以很轻易的来举行jsonp操纵了。
<script type="text/javascript">
$.getJSON('http://example.com/data.php?callback=?,function(jsondata)'){
//处置惩罚获得的json数据
});
</script>
jquery
会自动天生一个全局函数来替代callback=?
中的问号,以后猎取到数据后又会自动烧毁,实际上就是起一个暂时代办函数的作用。$.getJSON
要领会自动推断是不是跨域,不跨域的话,就挪用一般的ajax
要领;跨域的话,则会以异步加载js文件的情势来挪用jsonp
的回调函数。
JSONP的优瑕玷
JSONP的长处是:它不像XMLHttpRequest
对象完成的Ajax要求那样遭到同源战略的限定;它的兼容性更好,在越发陈旧的浏览器中都能够运转,不须要XMLHttpRequest或ActiveX的支撑;而且在要求终了后能够经由过程挪用callback的体式格局回传效果。
JSONP的瑕玷则是:它只支撑GET要求而不支撑POST等别的范例的HTTP要求;它只支撑跨域HTTP要求这类状况,不能处置惩罚差别域的两个页面之间怎样举行JavaScript
挪用的题目。
CORS和JSONP对照
CORS与JSONP比拟,无疑更加先进、轻易和牢靠。
1、 JSONP只能完成GET要求,而CORS支撑一切范例的HTTP要求。
2、 运用CORS,开发者能够运用一般的XMLHttpRequest提议要乞降获得数据,比起JSONP有更好的错误处置惩罚。
3、 JSONP重要被老的浏览器支撑,它们每每不支撑CORS,而绝大多数当代浏览器都已支撑了CORS)。
经由过程修正document.domain来跨子域
浏览器都有一个同源战略,其限定之一就是第一种要领中我们说的不能经由过程ajax的要领去要求差别源中的文档。 它的第二个限定是浏览器中差别域的框架之间是不能举行js的交互操纵的。
差别的框架之间是能够猎取window对象的,但却没法猎取相应的属性和要领。比方,有一个页面,它的地点是http://www.example.com/a.html
, 在这个页面内里有一个iframe
,它的src是http://example.com/b.html
, 很显然,这个页面与它内里的iframe
框架是差别域的,所以我们是没法经由过程在页面中誊写js代码来猎取iframe
中的东西的:
<script type="text/javascript">
function test(){
var iframe = document.getElementById('ifame');
var win = document.contentWindow;//能够猎取到iframe里的window对象,但该window对象的属性和要领几乎是不可用的
var doc = win.document;//这里猎取不到iframe里的document对象
var name = win.name;//这里一样猎取不到window对象的name属性
}
</script>
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
这个时刻,document.domain
就可以够派上用场了,我们只需把http://www.example.com/a.html
和 http://example.com/b.html
这两个页面的document.domain都设成雷同的域名就可以够了。但要注重的是,document.domain的设置是有限定的,我们只能把document.domain设置成本身或更高一级的父域,且主域必需雷同。
1.在页面 http://www.example.com/a.html
中设置document.domain
:
<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>
<script type="text/javascript">
document.domain = 'example.com';//设置成主域
function test(){
alert(document.getElementById('iframe').contentWindow);//contentWindow 可获得子窗口的 window 对象
}
</script>
2.在页面 http://example.com/b.html
中也设置document.domain
:
<script type="text/javascript">
document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain雷同
</script>
修正document.domain
的要领只适用于差别子域的框架间的交互。
运用window.name来举行跨域
window
对象有个name
属性,该属性有个特性:即在一个窗口(window)的生命周期内,窗口载入的一切的页面都是同享一个window.name
的,每一个页面临window.name
都有读写的权限,window.name
是耐久存在一个窗口载入过的一切页面中的
运用HTML5的window.postMessage要领跨域
window.postMessage(message,targetOrigin)
要领是html5
新引进的特性,能够运用它来向别的的window
对象发送音讯,不管这个window对象是属于同源或差别源,现在IE8+、FireFox、Chrome、Opera
等浏览器都已支撑window.postMessage
要领。