当然,“近乎完美”仅仅是个人观点,但如下所述,它确实简单而颇有效益!
一直在寻求一种自己满意的 JS 跨域方式(这里是指任意跨域),曾经了解过:
无意中看到一篇文章 《使用 window.name 解决跨域问题》……豁然开朗! 俺的问题终于解决了。
对那个实现小改了一下,加了浏览器本地设置 Window.name 的功能,实现浏览器“本地”异域数据的传递(如从浏览器窗口A传递数据到窗口B,仅在本地进行,且两个域不同)——这会产生一个很蛙王的应用(下一篇文章《普通 http 网络下数据的安全传输》将详细说明,本文后有少量提及)。感谢网络! 也感谢愿意分享的技术达人!
下面贴出俺的代码,也分享一下,呵呵……
(注意:本地需要创建一个名为 proxy.html 的空文件)
使用:
如果需要同时访问多个异域文件,可以像下面这样写回调函数,浏览器异步载入 iframe 的机制形成了天生的 JS 跨域异步访问。
这是跨域请求的主页面 JS 调用:
http://www.aaa.com/test4.html 中的内容:(跨域网络数据传递)
http://www.eee.com/test8.html 中的内容:(跨域本地数据转递应用。注意:这里是普通的 http 协议)
呵呵……是否期待下一篇文章《普通 http 网络下数据的安全传输》呢?
注: 附件包含本跨域实现和前几篇关于 JS 文字加密算法的实现代码。
===============================================================================
修 订:
如此赋值在 firefox 中会导致历史记录的产生,可用 Location.replace() 代替,如下:
一直在寻求一种自己满意的 JS 跨域方式(这里是指任意跨域),曾经了解过:
- 即时插入 script 元素的方式,会让脚本立即执行,不安全,并且需要与跨域的远端做好约定——比如变量名。细节较为繁琐。
- 写 iframe 的 location.hash 的方式,会导致历史记录的产生,且数据量有限,同时,因为 URL 的内容可视,既不好看也容易泄露信息。
- 用代理? 虽然算是最“正宗”的完整跨域方案,但太麻烦了点——首先得有代理,如果量大的话,代理的负担会很重,会导致“瓶颈”制约。
- 利用 Flash 跨域,不在考虑之列——复杂了些,并且那不算是 JS 跨域。
无意中看到一篇文章 《使用 window.name 解决跨域问题》……豁然开朗! 俺的问题终于解决了。
对那个实现小改了一下,加了浏览器本地设置 Window.name 的功能,实现浏览器“本地”异域数据的传递(如从浏览器窗口A传递数据到窗口B,仅在本地进行,且两个域不同)——这会产生一个很蛙王的应用(下一篇文章《普通 http 网络下数据的安全传输》将详细说明,本文后有少量提及)。感谢网络! 也感谢愿意分享的技术达人!
下面贴出俺的代码,也分享一下,呵呵……
(注意:本地需要创建一个名为 proxy.html 的空文件)
- (function() {
- var _isIE = (
- navigator.appName == "Microsoft Internet Explorer"
- );
- var _removeNode = _isIE ? function() {
- var d;
- return function(n) {
- if(n && n.tagName != 'BODY') {
- d = d || document.createElement('div');
- d.appendChild(n);
- d.innerHTML = '';
- }
- }
- }() : function(n) {
- if(n && n.parentNode && n.tagName != 'BODY') {
- n.parentNode.removeChild(n);
- }
- };
- /* [ Request by window.name ]
- * ****************************************************************************
- 借助 Window.name 实现 Js 的跨域访问。
- 1、 url 向外传值, callback 处理返回结果。
- 2、 返回页面中 JS 对 window.name 赋值。
- 返回页
- <script language="JavaScript">
- window.name = ... // 支持 JSON 字符串,可达~2MB
- </script>
- 若需同时进行多个请求,回调函数应是不同的函数实例。
- iframe 的自由载入形成了异步机制。
- */
- wnRequest = {
- _doc: document,
- _proxyUrl: 'proxy.html'
- };
- wnRequest.send = function( url, callback )
- {
- if(! url || typeof url !== 'string') {
- return;
- }
- url += (url.indexOf('?') > 0 ? '&' : '?') + 'windowname=get';
- var frame = this._doc.createElement('iframe');
- frame._state = 0;
- this._doc.body.appendChild(frame);
- frame.style.display = 'none';
- (function( el, type, fn ) {
- if (_isIE) {
- el.attachEvent('on' + type, fn);
- } else {
- el.addEventListener(type, fn, false);
- }
- })(frame, 'load', function() {
- if(frame._state == 1) {
- _getData(frame, callback);
- } else if(frame._state == 0) {
- frame._state = 1;
- //frame.contentWindow.location = wnRequest._proxyUrl;
- frame.contentWindow.location.replace(wnRequest._proxyUrl);
- }
- });
- frame.src = url;
- };
- //
- // 设置异域 Js 可访问的本地数据,客户端直接站间转递数据
- // 注:
- // 即浏览器直接将数据转递给另一个域的窗口,数据不上网。
- // 返回页代码:
- // <script type="text/javascript">
- // if (window.name) {
- // //... 处理 name 值
- // window.name = null;
- // }
- // // 升为顶级窗口,完成数据转递
- // try {
- // top.location.hostname;
- // if (top.location.hostname != window.location.hostname) {
- // top.location.href =window.location.href;
- // }
- // } catch(e) {
- // top.location.href = window.location.href;
- // }
- // </script>
- //
- //
- wnRequest.setname = function( name, url ) {
- if(! url || typeof url !== 'string') {
- return;
- }
- url += (url.indexOf('?') > 0 ? '&' : '?') + 'windowname=loc';
- var frame = this._doc.createElement('iframe');
- frame._count = 0;
- this._doc.body.appendChild(frame);
- frame.style.display = 'none';
- if (_isIE) {
- frame.name = name;
- } else {
- frame.contentWindow.name = name;
- }
- frame.src = url;
- };
- //
- // 私用辅助
- //
- var _clear = function(frame) {
- try {
- frame.contentWindow.document.write('');
- frame.contentWindow.close();
- _removeNode(frame);
- } catch(e) {}
- }
- var _getData = function(frame, callback) {
- try {
- var da = frame.contentWindow.name;
- } catch(e) {}
- _clear(frame);
- if(callback && typeof callback === 'function') {
- callback(da);
- }
- }
- })();
使用:
如果需要同时访问多个异域文件,可以像下面这样写回调函数,浏览器异步载入 iframe 的机制形成了天生的 JS 跨域异步访问。
这是跨域请求的主页面 JS 调用:
- <script language="javascript">
- var _str = '', _cnt = 0;
- function myfunc( id ) {
- return function( data ) {
- _str += id + ':' + data + '\n';
- ++_cnt;
- if (_cnt >= 4) alert(_str);
- };
- }
- var _links = [
- { id: 4, url: 'http://www.aaa.com/test4.html' },
- { id: 5, url: 'http://www.bbb.com/test5.html' },
- { id: 6, url: 'http://www.ccc.com/test6.html' },
- { id: 7, url: 'http://www.ddd.com/test7.html' }
- ];
- function dosome() {
- for (var _i=0; _i<_links.length; ++_i) {
- wnRequest.send(_links[_i].url, myfunc(_links[_i].id));
- }
- // 跨域本地数据转递
- wnRequest.setname('这里可能是一串加密用的密钥哦,俺从 https 那边过来滴!', 'http://www.eee.com/test8.html');
- }
- </script>
http://www.aaa.com/test4.html 中的内容:(跨域网络数据传递)
- <script type="text/javascript">
- window.name='返回的数据,可以是 JSON 格式';
- </script>
http://www.eee.com/test8.html 中的内容:(跨域本地数据转递应用。注意:这里是普通的 http 协议)
- <script type="text/javascript">
- if (window.name) {
- alert(window.name);
- // 存储或处理 name 值
- // 可存在 Cookie 中,如果不希望 Cookie 上传泄露出去,可设置其 secure 属性
- window.name = null;
- }
- /*
- try {
- top.location.hostname;
- if (top.location.hostname != window.location.hostname) {
- top.location.href =window.location.href;
- }
- } catch(e) {
- top.location.href = window.location.href;
- }
- */
- </script>
呵呵……是否期待下一篇文章《普通 http 网络下数据的安全传输》呢?
注: 附件包含本跨域实现和前几篇关于 JS 文字加密算法的实现代码。
===============================================================================
修 订:
- frame.contentWindow.location = wnRequest._proxyUrl;
如此赋值在 firefox 中会导致历史记录的产生,可用 Location.replace() 代替,如下:
- frame.contentWindow.location.replace(wnRequest._proxyUrl);