为了Javascript的安全性,不允许跨域调用其他页面的对象。但与此同时,注入iframe或ajax应用也带来了很多麻烦。在这里,我简单梳理一下一些跨领域的问题。
什么是跨域

首先,什么是跨域?简单理解为a.com域名下的Javascript由于Javascript同源策略的限制,无法操作b.com或c.a.com域名下的对象。有关更详细的解释,请参见下表:
特别注意两点:
如果“前台”对协议和端口导致的跨域问题无能为力,在跨域问题上,只通过URL的头标识域,而不去尝试判断同一个ip地址对应两个域还是两个域在同一个ip上。URL的头指的是window . location . protocol+window . location . host,也可以理解为域、协议、端口必须匹配。
document.domain+iframe的设置
对于主域相同但子域不同的例子,可以通过设置document.domain来解决,具体方法是在http://www.a.com/a.com和http://script.a.com/b.html文件中分别添加document.domain = 'a.com ',然后在a.html文件中创建一个iframe来控制iframe的contentdocument,这样两个JS文件就可以“交互”了。当然,这种方法只能解决一级域相同而二级域不同的情况。如果你异想天开地将script.a.com的多米安设为Alibaba.com,显然会报错。代码如下:
A.html在www.a.com
document . domain = ' a . com ';var ifr = document.createElementIFR . src = ' http://script . a . com/b . html ';IFR . style . display = ' none ';document . body . appendchild;IFR . onload = function { var doc = IFR . content document | | IFR . content window . document;//操作b.htmlalert [0]。子节点[0]。此处为nodevalue};
B.html在script.a.com
document . domain = ' a . com ';
这种方法适用于www.kuqin.com、kuqin.com、script.kuqin.com和css.kuqin.com的任何页面之间的相互通信。
注意:默认情况下,页面的域等于window.location.hostname。主域名是没有www的域名,比如a.com。主域名前面的前缀通常是二级域名或多级域名。例如,www.a.com实际上是一个二级域名。域名只能设置为主域名,不能设置为b.a.com的c.a.com。
问题:
安全性,当一个网站b.a.com受到攻击,另一个网站c.a.com就会造成安全漏洞。如果一个页面中引入了多个iframe,为了操作所有的iframe,必须设置相同的域。
动态创建脚本
虽然浏览器默认禁止跨域访问,但并不禁止在页面中引用其他域的JS文件,可以自由执行引入的JS文件中的功能。根据这一点,通过创建脚本节点,可以方便地实现完全的跨域通信。详情请参考YUI的Get实用程序
判断脚本节点是加载的还是挺有意思的:IE只能传递脚本的readystatechange属性,其他浏览器都是脚本的加载事件。以下是一些判断脚本加载的方法。
js . onload = js . onreadystatechange = function { if {//callback此处执行js . onload = js . onreadystatechange = null;}};
使用iframe和location.hash
这种方法比较迂回,但是可以解决完全跨域情况下的足迹替换问题。原理是使用location.hash来传递值。http://a.com中的# hello world # hello word是location.hash更改hash不会导致页面刷新,所以hash值可以用于数据传输。当然,数据容量有限。假设域名a.com下的文件cs1.html要和域名he11oworld.com下的cs2.html传递信息,cs1.html先自动创建一个隐藏的iframe,iframe的src指向域名he11oworld.com下的cs2.html页面。此时,哈希值可用于参数传递。在cs2.html响应请求后,它将通过修改cs1.html的哈希值来传递数据。同时,在cs1.html中加入一个定时器,每隔一段时间判断location.hash的值是否有变化,如果有变化,则获取哈希值。代码如下:

第一,a.com下的文件,cs1.html文件:
函数start request { var IFR = document . createelement;IFR . style . display = ' none ';IFR . src = ' http://run . wenjings . com/code/#/# param do ';document . body . appendchild;}函数check hash { try { var data = location . hash location . hash . substring:' ';if { console.log}}抓{ };} setInterval
he11oworld.com域名下的Cs2.html:
//模拟一个简单的参数处理操作开关{case '#paramdo ':回调;打破;case ' # paramset '://做点什么……break;}函数回调{ try { parent . location . hash = ' some data ';} catch {// ie,chrome的安全机制无法修改parent.location.hash,//所以我们要利用he11oworld域下的一个中间代理iframe var IFR proxy = document . createelement;IFR proxy . style . display = ' none ';IFR proxy . src = ' http://www . Wenxi Yan . org/# somedata ';//注意文件是“a.com”域下的document . body . appendchild;}}
A.com的域名cs3.html
//因为parent.parent和自身属于同一个域,所以可以更改其location . hash parent . parent . location . hash = self . location . hash . substring的值;
当然,这种方式也有很多缺点,比如数据直接暴露在url中,数据容量和类型有限等...
利用window.name实现跨域数据传输
有三页:
A.com/app.html:申请页面。A.com/proxy.html:代理文件,通常是没有任何内容的html文件,需要与应用程序页面在同一个域中。B.com/data.html:应用页面需要获取数据,可以称为数据页面。
实现它的基本步骤如下:
在应用程序页a.com/app.html中创建一个iframe,并将其src指向数据页b.com/data.html.。该页会将数据附加到窗口。输入此iframe的名称。data.html电码如下:
window.name = '我在那里!';//这里是要传输的数据。大小一般是2M,在IE和firefox下可以大到32M左右。//数据格式可以自定义,比如json和string。
在应用页面中监听iframe的onload事件,在该事件中设置该iframe的代理文件,其src指向本地域。app.html的一些代码如下:
var state = 0,iframe = document.createElement,load fn = function { if { var data = iframe . content window . name;//读取数据告警;//弹出‘我在那里!’} else if { state = 1;iframe . content window . location = " http://a . com/proxy . html ";//设置代理文件} };iframe . src = ' http://b . com/data . html ';if { iframe.attachEvent} else { iframe.onload = loadfn} document . body . appendchild;
获取数据后销毁这个iframe并释放内存,这样也保证了安全性不被其他域框架js访问。
iframe . content window . document . write;iframe . content window . close;document . body . remove child;
综上所述,iframe的src属性由外域转移到本域,跨域数据由iframe的window.name由外域转移到本域。这样巧妙地绕过了浏览器的跨域访问限制,但同时又是一种安全的操作。

使用HTML5邮件
HTML5中最酷的新特性之一是跨文档消息传递。下一代浏览器将支持该功能:Chrome 2.0+,Internet Explorer 8.0+,Firefox 3.0+,Opera 9.6+,Safari 4.0+。脸书已经使用这个功能来支持基于网络的实时消息传递。
OtherWindow:对接收信息页的窗口的引用。可以是页面中iframe的contentWindow属性,window.open的返回值,也可以是window.frames按名称或下标获取的值。Message:要发送的数据的字符串类型。TargetOrigin:用于限制otherWindow,*表示没有限制。
a.com/index.html:代码
b.com/index.html:代码


