这篇文章上次修改于 956 天前,可能其部分内容已经发生变化,如有疑问可询问作者。 [TOC] # 跨域常识 ## 同源策略 同源指的就是协议相同、域名相同、端口号相同,三个条件必须全部匹配,否则就会受到浏览器的安全限制. 限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。 跨域可以通过标签元素实现,例如link、script、img、iframe等标签。 ## JSONP跨域 在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。网页通过添加一个` ``` data.php 后端提供数据和对前端js函数进行回调。 ``` ``` 访问http://sec.wbs.im/jsonp.html,回调拿到数据。  ## window.name window对象有一个name属性,该属性有一个特征:即在一个窗口的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每一个页面对window.name都有读写的权限,window.name是持久的存在于一个窗口载入的所有页面中的,并不会因为新的页面的载入而被重置。 window.name的值只能是字符串的形式,这个字符串的大小最大只能允许2M左右,具体取决于不同的浏览器,但是一般是够用了。 **理论测试** a.html ``` aaa ``` b.html ``` bbb ``` 先访问http://cross-domian-a.wbs.im/a.html  再访问http://cross-domian-a.wbs.im/b.html,成功获取到数据。  再访问http://cross-domian-b.wbs.im/b.html,成功获取到数据。  **借助iframe获取数据** 充当中间人的iframe.html想要获取到a.html中通过window.name设置的数据,必须把这个iframe的src设置成跟a.html页面同一个域才行,不然根据同源策略,iframe.html是不能访问到iframe中的window.name属性的。 ``` ``` nodata.html ``` nodata ``` 访问http://cross-domian-b.wbs.im/iframe.html,获取到数据。  ## document.domain 有一个页面,它的地址是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取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,因为主域已经不相同了。   这样我们就可以通过js访问到iframe中的各种属性和对象了。不过如果你想在http://www.example.com/a.html 页面中通过ajax直接请求http://example.com/b.html 页面,即使你设置了相同的document.domain也还是不行的,所以修改document.domain的方法只适用于不同子域的框架间的交互。如果你想通过ajax的方法去与不同子域的页面交互,除了使用jsonp的方法外,还可以用一个隐藏的iframe来做一个代理。原理就是让这个iframe载入一个与你想要通过ajax获取数据的目标页面处在相同的域的页面,所以这个iframe中的页面是可以正常使用ajax去获取你要的数据的,然后就是通过我们刚刚讲得修改document.domain的方法,让我们能通过js完全控制这个iframe,这样我们就可以让iframe去发送ajax请求,然后收到的数据我们也可以获得了。 ## window.postMessage方法 window.postMessage方法是HTML5中新引进的特性。 可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。 调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。 需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。    ## CORS 跨域资源共享 CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。 浏览器将跨域资源共享cors分为了两种方式,一种方式就是简单请求,另外一种自然就是非简单请求。只要同时满足下面的两大条件......[更多点此](http://www.ruanyifeng.com/blog/2016/04/cors.html) ## 参考资料 [javascript跨域的4种方法和原理详解](https://www.jb51.net/article/48794.htm) [JavaScript跨域总结与解决办法](https://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html) [跨域资源共享 CORS 详解](http://www.ruanyifeng.com/blog/2016/04/cors.html)