详解js跨域题目

什么是跨域?

观点:只需协定、域名、端口有任何一个差别,都被看成是差别的域。

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.htmlhttp://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要领。

    原文作者:trigkit4
    原文地址: https://segmentfault.com/a/1190000000718840
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞