window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的。window.name属性的神奇之处在于name 值在不同的页面(甚至不同域名)加载后依旧存在(如果没修改则值不会变化),并且可以支持非常长的 name 值(2MB)。
window.name = data;//父窗口先打开一个子窗口,载入一个不同源的网页,该网页将信息写入。
location = 'http://parent.url.com/xxx.html';//接着,子窗口跳回一个与主窗口同域的网址。
var data = document.getElementById('myFrame').contentWindow.name。//然后,主窗口就可以读取子窗口的window.name了。
1、同源策略
同源策略限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。
一个源的定义:如果协议,端口(如果指定了一个)和主机对于两个页面是相同的,则两个页面具有相同的源。
下表给出了相对 http://store.company.com/dir/page.html 同源检测的示例:
2、主域相同的跨域
页面可能会更改其自己的来源,但有一些限制。脚本可以将 document.domain的值设置为其当前域或其当前域的超级域。如果将其设置为其当前域的超级域,则较短的域将用于后续原始检查。例如,假设文档中的一个脚本在 http://store.company.com/dir/other.html 执行以下语句:
这条语句执行之后,页面将会成功地通过对 http://company.com/dir/page.html 的同源检测。
3、完全不同源的跨域(两个页面之间的通信)
3.1、通过location.hash跨域
假设域名a.com下的文件cs1.html要和jianshu.com域名下的cs2.html传递信息。 1、cs1.html首先创建自动创建一个隐藏的iframe,iframe的src指向jianshu.com域名下的cs2.html页面。 2、cs2.html响应请求后再将通过修改cs1.html的hash值来传递数据。 3、同时在cs1.html上加一个定时器,隔一段时间来判断location.hash的值有没有变化,一旦有变化则获取获取hash值。
优点:1.可以解决域名完全不同的跨域。2.可以实现双向通讯。 缺点:location.hash会直接暴露在URL里,并且在一些浏览器里会产生历史记录,数据安全性不高也影响用户体验。另外由于URL大小的限制,支持传递的数据量也不大。有些浏览器不支持onhashchange事件,需要轮询来获知URL的变化。
3.2、通过window.name跨域
window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的。window.name属性的神奇之处在于name 值在不同的页面(甚至不同域名)加载后依旧存在(如果没修改则值不会变化),并且可以支持非常长的 name 值(2MB)。
如果是与iframe通信的场景就需要把iframe的src设置成当前域的一个页面地址。
3.3、通过window.postMessage跨域
HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。postMessage的兼容性如下:
可以看到 Internet Explorer 8+, chrome,Firefox , Opera 和 Safari 都将支持这个功能。但是Internet Explorer 8和9以及Firefox 6.0和更低版本仅支持字符串作为postMessage的消息。
postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送。
父窗口和子窗口都可以通过message事件,监听对方的消息。message事件的事件对象event,提供以下三个属性:
一个例子:
4、AJAX请求不同源的跨域
4.1、通过JSONP跨域
基本原理:网页通过添加一个 Githubissues.