使用 window.name 解决跨域传输
来源:互联网 发布:网络歌曲最经典500首 编辑:程序博客网 时间:2024/06/11 07:14
这篇文章是对 JavaScript跨域总结与解决办法 的补充。
有三个页面:
- a.com/app.html:应用页面。
- a.com/proxy.html:代理文件,一般是一个没有任何内容的html文件,需要和应用页面在同一域下。
- b.com/data.html:应用页面需要获取数据的页面,可称为数据页面。
实现起来基本步骤如下:
- 在应用页面(a.com/app.html)中创建一个iframe,把其src指向数据页面(b.com/data.html)。
数据页面会把数据附加到这个iframe的window.name上,data.html代码如下:<script type="text/javascript"> window.name = 'I was there!'; // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右 // 数据格式可以自定义,如json、字符串</script>
- 在应用页面(a.com/app.html)中监听iframe的onload事件,在此事件中设置这个iframe的src指向本地域的代理文件(代理文件和应用页面在同一域下,所以可以相互通信)。app.html部分代码如下:
<script type="text/javascript"> var state = 0, iframe = document.createElement('iframe'), loadfn = function() { if (state === 1) { var data = iframe.contentWindow.name; // 读取数据 alert(data); //弹出'I was there!' } else if (state === 0) { state = 1; iframe.contentWindow.location = "http://a.com/proxy.html"; // 设置的代理文件 } }; iframe.src = 'http://b.com/data.html'; if (iframe.attachEvent) { iframe.attachEvent('onload', loadfn); } else { iframe.onload = loadfn; } document.body.appendChild(iframe);</script>
- 获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)。
<script type="text/javascript"> iframe.contentWindow.document.write(''); iframe.contentWindow.close(); document.body.removeChild(iframe);</script>
总结起来即:iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。
参考文章:window.name Transport、Session variables without cookies、使用 window.name 解决跨域问题、利用window.name实现跨域访问的基本步骤、克军写的样例。
window.name 传输技术,原本是 Thomas Frank 用于解决 cookie 的一些劣势(每个域名 4 x 20 Kb 的限制、数据只能是字符串、设置和获取 cookie 语法的复杂等等)而发明的(详细见原文:《Session variables without cookies》),后来Kris Zyp 在此方法的基础上强化了 window.name 传输 ,并引入到了 Dojo (dojox.io.windowName),用来解决跨域数据传输问题。
window.name 的美妙之处:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
window.name 传输技术的基本原理和步骤为:
name 在浏览器环境中是一个全局/window对象的属性,且当在 frame 中加载新页面时,name 的属性值依旧保持不变。通过在 iframe 中加载一个资源,该目标页面将设置 frame 的 name 属性。此 name 属性值可被获取到,以访问 Web 服务发送的信息。但 name 属性仅对相同域名的 frame 可访问。这意味着为了访问 name 属性,当远程 Web 服务页面被加载后,必须导航 frame 回到原始域。同源策略依旧防止其他 frame 访问 name 属性。一旦 name 属性获得,销毁 frame 。
在最顶层,name 属性是不安全的,对于所有后续页面,设置在 name 属性中的任何信息都是可获得的。然而 windowName 模块总是在一个 iframe 中加载资源,并且一旦获取到数据,或者当你在最顶层浏览了一个新页面,这个 iframe 将被销毁,所以其他页面永远访问不到 window.name 属性。
基本实现代码,基于 YUI,源自克军写的样例:
(function(){ var YUD = YAHOO.util.Dom, YUE = YAHOO.util.Event; dataRequest = { _doc: document, cfg: { proxyUrl: 'proxy.html' } }; dataRequest.send = function(sUrl, fnCallBack){ if(!sUrl || typeof sUrl !== 'string'){ return; } sUrl += (sUrl.indexOf('?') > 0 ? '&' : '?') + 'windowname=true'; var frame = this._doc.createElement('iframe'), state = 0, self = this; this._doc.body.appendChild(frame); frame.style.display = 'none'; var clear = function(){ try{ frame.contentWindow.document.write(''); frame.contentWindow.close(); self._doc.body.removeChild(frame); }catch(e){} }; var getData = function(){ try{ var da = frame.contentWindow.name; }catch(e){} clear(); if(fnCallBack && typeof fnCallBack === 'function'){ fnCallBack(da); } }; YUE.on(frame, 'load', function(){ if(state === 1){ getData(); } else if(state === 0){ state = 1; frame.contentWindow.location = self.cfg.proxyUrl; } }); frame.src = sUrl; };})();
Web 服务器如何提供 window.name 数据
为了让 Web 服务器实现 window.name,服务器应该只寻找请求中是否包含 windowname 参数。如果包含了 windowname 参数,服务器应该返回一个设置了 window.name 字符串值的 HTML 文档,回应此请求并传送到客户端。例如:
http://www.planabc.net/getdata.html?windowname=true
如果服务器想用 Hello 响应客服端,它应该返回一个 HTML 页面:
<html> <script type="text/javascript"> window.name="Hello"; </script></html>
同样也可以转换为 JSON 数据:
<html> <script type="text/javascript"> window.name='{"foo":"bar"}'; </script></html>
如果你手动创建资源,书写大量的多行的 JSON 对象为一个引用的字符串应该是比较困难的并且易于出错的。可以使用这样的 HTML 样例简单的创建 JSON 数据,将会转换为一个 JSON 字符串而无需手动转义 JSON 为字符串:
同样的,如果你想传递 HTML/XML 数据,这里有一个样例实现,而无需手动将这些数据转换成字符串:
<html> <body> <p id="content"> some <strong>html/xml-style</strong>data </p> </body> <script type="text/javascript"> window.name = document.getElementById("content").innerHTML; </script></html>
window.name 传输技术相比其他的跨域传输的一些优势:
- 它是安全的。也就是说,它和其他的基于安全传输的 frame 一样安全,例如 Fragment Identifier messaging (FIM)和 Subspace。(I)Frames 也有他们自己的安全问题,由于 frame 可以改变其他 frame 的 location,但是这个是非常不同的安全溢出,通常不太严重。
- 它比 FIM 更快,因为它不用处理小数据包大小的 Fragment Identifier ,并且它不会有更多的 IE 上的“机关枪”声音效果。它也比 Subspace 快,Subspace 需要加载两个 Iframe 和两个本地的 HTML 文件来处理一个请求。window.name 仅需要一个 Iframe 和一个本地文件。
- 它比 FIM 和 Subspace 更简单和安全。FIM 稍微复杂,而 Subspace 非常复杂。Subspace 也有一些额外的限制和安装要求,如预先声明所有的目标主机和拥有针对若干不同特殊主机的 DNS 入口。window.name 非常简单和容易使用。
- 它不需要任何插件(比如 Flash)或者替代技术(例如 Java)。
- 使用 window.name 解决跨域传输
- 使用 window.name 解决跨域问题
- 使用 window.name 解决跨域问题
- 利用window.name解决跨域问题
- 实战window.name解决跨域问题
- 跨域请求之三:window.name解决跨域
- 使用window.name 进行数据跨域传递
- 使用window.name,比较完美的跨域解决方案
- window.name实现跨域
- Window.name实现跨域
- 近乎完美的简单 JS 跨域解决方式 --window.name
- 近乎完美的简单 JS 跨域解决方式 --window.name
- 近乎完美的简单 JS 跨域解决方式 --window.name
- 近乎完美的简单 JS 跨域解决方式 --window.name
- window.name实现的跨域数据传输
- window.name实现的跨域数据传输
- window.name实现的跨域数据传输
- window.name实现跨域请求
- C++ primer第二次阅读学习笔记(第17章:用于大型程序的工具:异常处理)
- NSArray与NSMutableArray的区别 NSDictionary以及NSMutableDictionary用法总结
- Microsoft Office Live Meeting(2007 版)产品概述
- JS-Demo1:JavaScript实现表格列拖动
- Altera下载脚本一
- 使用 window.name 解决跨域传输
- 指针详解
- 数据库安装及数据库问题解决方法(二)
- 雷锋微学堂:云计算平台最需要的10种工作技能
- Flex4之控制状态转换以及产生动画特效【登录示例】
- 用C扩展Python的功能
- linux下保护模式之CPL,RPL,DPL总结
- 渗透测试者的基本技能
- 导致vc程序崩溃的原因