`
Liner
  • 浏览: 141560 次
  • 性别: Icon_minigender_1
  • 来自: 西南边陲
社区版块
存档分类
最新评论

近乎完美的简单 JS 跨域解决方式 --window.name

阅读更多
当然,“近乎完美”仅仅是个人观点,但如下所述,它确实简单而颇有效益!

一直在寻求一种自己满意的 JS 跨域方式(这里是指任意跨域),曾经了解过:

  1. 即时插入 script 元素的方式,会让脚本立即执行,不安全,并且需要与跨域的远端做好约定——比如变量名。细节较为繁琐。
  2. 写 iframe 的 location.hash 的方式,会导致历史记录的产生,且数据量有限,同时,因为 URL 的内容可视,既不好看也容易泄露信息。
  3. 用代理? 虽然算是最“正宗”的完整跨域方案,但太麻烦了点——首先得有代理,如果量大的话,代理的负担会很重,会导致“瓶颈”制约。
  4. 利用 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);

分享到:
评论
13 楼 leafxf 2012-07-09  
这个和直接引用js有多大不同和优点?
12 楼 zhangyg 2011-05-11  
我怎么不行,我在执行到 var _getData = function(frame, callback) {
    var data="";
    try
    {
   
    data=frame.contentWindow.name;
   
    }
    catch(e)
    {
    alert(e.message +"," + e.description);
    }
      
        _clear(frame);
        if(callback && typeof callback === 'function') {
            callback(data);
          
        }
    }
catch 到的错误是拒绝访问
11 楼 Liner 2011-02-14  
sw1982 写道
jsonp才是正经的方案啊,呵呵

考虑过……
但 jsonp 没法实现浏览器本地的跨域传递数据,应用见《普通 http 网络下数据的安全传输》

>>即时插入 script 元素的方式,会让脚本立即执行,不安全,并且需要与跨域的远端做好约定……
jsonp 较适于对所跨的域的有较大控制权的情况,如果异域的 JS 不按规则办事,则可以破坏本域的 JS 逻辑。而 window.name 不存在这样的情况。
10 楼 sw1982 2011-02-14  
jsonp才是正经的方案啊,呵呵
9 楼 thihy 2011-02-10  
个人觉得不如JSONP
8 楼 guoshiguan 2011-02-10  
可以跨浏览器吗,
7 楼 十三‘’ 2011-02-10  
简单实用,很不错
6 楼 Liner 2011-02-10  
la_ka 写道
为什么setname()在send()的后面啊? 这样那些URL能得到传值吗? 不是很明白,,请指点啊

那只是个“用法”的示例,不是具体的应用
引用
for (var _i=0; _i<_links.length; ++_i) { 
        wnRequest.send(_links[_i].url, myfunc(_links[_i].id)); 
}

批量 send 的用法
引用
wnRequest.setname('这里可能是一串加密用的密钥哦,俺从 https 那边过来滴!', 'http://www.eee.com/test8.html');

本地不同域数据转递的用法


5 楼 la_ka 2011-02-09  
# for (var _i=0; _i<_links.length; ++_i) { 
#             wnRequest.send(_links[_i].url, myfunc(_links[_i].id)); 
#         } 
#         // 跨域本地数据转递 
#         wnRequest.setname('这里可能是一串加密用的密钥哦,俺从 https 那边过来滴!', 'http://www.eee.com

为什么setname()在send()的后面啊? 这样那些URL能得到传值吗? 不是很明白,,请指点啊
4 楼 la_ka 2011-02-09  
听说过,今天才知道JSONP是这样啊,多谢LZ了,其实还是没明白为什么要跨域去传这些东西,还是用JS。。。
3 楼 rainsilence 2011-02-08  
jsonp
2 楼 Liner 2011-02-05  
zhangxingliang 写道
这个方式,需要 A B域的东西都要在代码里做一点事情

还不如直接引用js


愿闻其详
1 楼 zhangxingliang 2011-02-05  
这个方式,需要 A B域的东西都要在代码里做一点事情

还不如直接引用js

相关推荐

    Tomcat解决跨域的两个jar包java-property-utils-1.9.jar和cors-filter-1.7.jar

    在开发Web应用时,跨域问题常常困扰着开发者。跨域是由于浏览器的同源策略(Same-Origin Policy)限制,导致不同源的请求无法互相访问。然而,随着现代Web服务的发展,API接口的广泛使用,跨域问题变得越来越普遍。...

    cors-filter-1.7.jar,cors-filter-2.5.jar,cors-filter-2.10.jar

    Tomcat作为一款广泛使用的Java Web服务器,提供了一种方式来处理跨域请求,这就是我们今天要讨论的“cors-filter”jar包。 标题中的“cors-filter-1.7.jar”,“cors-filter-2.5.jar”和“cors-filter-2.10.jar”是...

    cors-filter-1.7.jar 和 java-property-utils-1.9.jar

    CORS为解决这个问题提供了一种安全的方式。 `cors-filter-1.7.jar` 和 `java-property-utils-1.9.jar` 是在Java环境中实现CORS跨域访问时常用的两个库。`cors-filter-1.7.jar` 包含了一个过滤器,该过滤器能够处理...

    cors-filter-1.7.jar spring解决跨域问题 java

    二、Spring解决跨域问题的两种方式 1. 使用`@CrossOrigin`注解: 在Spring MVC的Controller或者Controller方法上使用`@CrossOrigin`注解,可以直接指定允许跨域的源、请求方法、请求头等信息。例如: ```java ...

    cors-filter-1.7.jar java-util-1.9.1.jar

    在IT行业中,跨域资源共享(CORS)是一个关键的安全特性,尤其在Web应用程序开发中,它涉及到浏览器的同源策略。同源策略是浏览器的一种安全机制,限制了来自不同源的HTTP请求,以防止恶意网站读取或修改敏感数据。...

    cors-filter-1.7.jar,java-property-utils-1.9.jar

    在IT行业中,尤其是在Web开发领域,跨域资源共享(CORS,Cross-Origin Resource Sharing)是一个重要的概念,它允许浏览器向不同源的服务器发送Ajax请求。在这个场景中,我们关注的两个jar包——"cors-filter-1.7....

    window.name解决跨域问题的文档

    window.name 解决跨域问题的文档 window.name 传输技术是 Thomas Frank 发明的,旨在解决 cookie 的一些劣势,例如每个域名 4 x 20 Kb 的限制、数据只能是字符串、设置和获取 cookie 语法的复杂等等。后来,Kris ...

    cors-filter-1.7.jar和java-property-utils-1.9.jar

    在Jaspersoft JasperServer环境下,这两个库的结合使用可以提供一套完整的解决方案,使得Web应用程序能够跨域访问报表和数据,同时方便地管理和操作服务器的配置信息。CORS过滤器确保了跨域请求的安全性,而Java属性...

    java-property-utils-1.9.1.jar,java-property-utils-1.10.jar

    在给定的场景中,`java-property-utils-1.9.1.jar` 和 `java-property-utils-1.10.jar` 是这个库的两个不同版本,它们被用在Tomcat服务器上进行跨域设置。在Web开发中,跨域问题是一个常见的挑战,它涉及到浏览器的...

    java-property-utils-1.9.1等.zip

    跨域请求时,页面报错“Access-Control-Allow-Origin”, 因为浏览器只允许请求当前域的资源,而对其他域的资源表示不信任。需要配置cors全称是"跨域资源共享"(Cross-origin resource sharing)。以tomcat为例子在 ...

    aliyun-oss-sdk-6.1.1.min.js

    OSS Browser.js SDK基于Node.js环境构建,通过Browserify和Babel产生适用于浏览器的代码。 但是由于浏览器环境的特殊性,无法使用以下功能: 流式上传:浏览器中无法设置chunked编码,用分片上传替代。 操作本地...

    解决Tomcat跨域的jar包,java-property-utils-1.9.jar

    这里提到的`java-property-utils-1.9.jar`并不是直接解决跨域问题的库,但它可能在配置或辅助处理跨域问题的过程中起到一定作用,因为它是一个Java属性处理工具包。 `java-property-utils`这个库主要用来处理Java的...

    cors-filter-2.5.jar

    在描述中提到,“解决java web应用跨域问题”,这指的是当JavaScript尝试从一个域名访问另一个域名的资源时,由于浏览器的安全策略,这种请求通常会被阻止。CORS Filter是为了解决这个问题而设计的,它提供了一种...

    cors-filter-2.5 + java-property-utils-1.9.1.zip

    如果允许,它会在响应头中添加`Access-Control-Allow-Origin`、`Access-Control-Allow-Methods`、`Access-Control-Allow-Headers`等字段,告知浏览器服务器支持的跨域请求方式。例如,`cors-filter-2.5.jar`是这个...

    最全面关于J2EE跨域资源共享的解决方案以及所需要依赖的Jar包,cors-filter-1.7.jar,java-property-utils-1.9.jar

    最全面关于J2EE跨域资源共享的解决方案以及所需要依赖的Jar包,cors-filter-1.7.jar,java-property-utils-1.9.jar, tomcat配置方法连接 http://bsxsb.com/index.php/2015/08/07/tomcat下通过cors实现跨域配置/

    tomcat跨域cors相关jar包 cors-filter-1.7.jar和java-property-utils-1.9.jar

    标题中的“tomcat跨域cors相关jar包 cors-filter-1.7.jar和java-property-utils-1.9.jar”指的是在Apache Tomcat服务器上处理跨域请求时所用到的两个关键库。CORS(Cross-Origin Resource Sharing)是现代Web应用...

    谷歌跨域插件allow-cors-access-control.zip

    标题中的“谷歌跨域插件allow-cors-access-control.zip”指的是一个用于解决浏览器跨域问题的Chrome插件。跨域资源共享(CORS)是一种机制,它允许Web应用程序从不同的源请求资源,比如JavaScript通过Ajax从非同源的...

    cors-filter-1.7.jar,java-property-utils-1.9.jar两个包供学习使用.rar

    总的来说,CORS-filter-1.7.jar和java-property-utils-1.9.jar这两个库在Java Web开发中扮演着重要角色,一个是解决前后端跨域问题,另一个则是处理配置文件的读写。理解并掌握这两个库的使用,对于提升Web应用的...

Global site tag (gtag.js) - Google Analytics