window.name作为数据传输:一种有效的方法?

49

概述和原始问题

window.name 是一个有趣的东西。MDN的描述暗示了最初的意图:

窗口的名称主要用于设置超链接和表单的目标。窗口不需要具有名称。

所以,这意味着我们可以在该窗口中打开控制台,并编写:

var win = window.open('http://google.com', 'el goog');

...然后让它通过弹出窗口拦截器,这应该会在一个名为“el goog”的窗口中打开google.com。由于同源策略,我无法访问win的name属性,但是如果我在新窗口中打开控制台并输入name,我将得到“el goog”的结果。如果我将窗口发送回我打开它的域(在本例中为stackoverflow.com),我可以获取name属性,并且它没有改变。
win.location.replace(location.href);
win.name; // "el goog"

这意味着我们可以通过设置窗口的name属性来拥有一种跨域会话存储方式。
如果在将窗口发送回原始域之前,google.com已经更改了window.name的值,那么我们将看到新值而不是"el goog"。这可以用作跨域数据传输,类似于JSONP或CORS的实用工具。
我搜索了一下以找到更多信息,显然dojo 认为它是合法的作为一种传输方式。然而,这并没有完全让我放心。所以我的问题是,是否有任何知名网站使用window.name作为数据传输?我认为这应该很容易发现,因为他们的文档会说类似于"将'callback'添加到查询字符串中用于JSONP,或者添加'whatever'用于window.name,"但我从未见过这样的内容。有人真的在实际应用中发现了吗?

备选问题

可能没有人真正使用这种技术;如果是这样的话(正如Rob W所指出的),上面的问题就无法回答。因此,我备选的问题是,这种方法有什么问题?这可能有助于解释为什么它并没有被广泛采用。

在我看来,这种方法至少有两个优点,相比JSONP而言:

  • 使用JSONP时,您需要信任来自外部源的脚本在您的域上运行。而使用window.name,由恶意站点包含的任何脚本都将在其自己的域上运行。

  • 使用JSONP时,无法传递大数据(任何太大而无法通过URL传递的数据),也无法进行HTTP POST。而使用window.name,我们可以发布任意大小的任意数据。

那么,这种方法有什么缺点呢?


示例实现

这是一个非常简单的客户端实现示例。它只处理GET请求,不处理POST请求。

function fetchData(url, callback) {
    var frame = document.createElement('iframe');
    frame.onload = function() {
        frame.onload = function() {
            callback(frame.contentWindow.name);
            frame.parentNode.removeChild(frame);
        }
        frame.src = 'about:blank';
    }
    frame.src = url;
    document.body.appendChild(frame);
}

// using it

fetchData('http://somehost.com/api?foo=bar', function(response) {

    console.log(response);

});​

我已经设置了一个fiddle来测试它 这里。 它使用这个脚本作为测试服务器。

这是一个稍微长一点的例子,可以进行POST请求:http://jsfiddle.net/n9Wnx/2/


摘要

据我所知,window.name并没有成为数据传输的主流方式。我想知道我的看法是否准确(因此提出了这个问题),如果是的话,我想知道为什么会这样。我列出了一些window.name似乎比JSONP具有的优点。有人能否找出一些可能导致阻止采用此技术的缺点

更重要的是,有人能给我一个充分的理由,说明我不应该使用window.name作为数据传输吗?


@RobW,就像“是的,blahboop.com API将使用JSONP或window.name来响应请求…” 这样的东西,blahboop.com是人们真正使用的东西。这样可以为这个想法增加一些合法性。我相信我能够处理好实现过程,但是看到一个真正使用这种技术的网站可能会让人觉得更可靠(至少这种行为不太可能在将来被删除)。 - Dagg Nabbit
@RobW 我曾经考虑过这个问题,但感觉自己似乎在问:“为什么没有人使用这种技术”,而我并不确定是否真的没有人使用它,所以我想先询问一下。 - Dagg Nabbit
@DaggNabbit,您能否回答我的相关问题:http://stackoverflow.com/questions/19487729/cross-domain-using-window-name-double-onload-should-be-used? - Royi Namir
1
http://www.thomasfrank.se/sessionvars.html所使用的方法 - Brett Zamir
1
@MrChrisRodriguez,听起来这对你正在做的事情很有效,但你可能还想了解一下postMessage。 - Dagg Nabbit
显示剩余8条评论
2个回答

6

window.name并不是一个特别好的传输方式,因为(据我所知)当它被更改时并不会触发任何事件。因此,试图将 window.name 用作双向通信渠道的应用程序必须定期轮询其更新。

就实际使用它的网站而言:我从未听说过任何。可能有一些,但我只在纯理论层面上讨论过这种技术。


有趣的是,我刚想到这个事件的事情。我觉得类似myIframe.onload=finishRequest; myIframe.src='somehost.com/api/?id=123'这样的代码应该可以很好地工作... - Dagg Nabbit
我已经在问题中添加了一个基于事件的示例。这是你想要的吗?你还能想到其他什么可能使它不成为良好的数据传输方式吗? - Dagg Nabbit
@AwalGarg 你无法向另一个源的窗口发送事件。 - user149341

3
更重要的是,有人能给我一个充分的理由,为什么我不应该使用window.name作为数据传输方式吗?
尽管在跨域变化时,window.name可以成为真正的救世主,但它不能作为真正的通用数据传输机制的原因在于缺乏存储和检索数据的API。例如,localStorage提供了setItemgetItem等API。这样的API有助于抽象化值实际存储的方式,并防止格式冲突(如果在您的端上运行的不同库以不同的格式存储,则会出现此类冲突)。
就我所知,window.name并没有成为数据传输的主流方式。我想知道是否我的看法准确(这也是最初的问题),如果是这样,我想知道原因是什么。
由于window.name没有提供这样的存储/检索抽象层,正如我上面所述,第三方库无法知道在将数据存储在window.main时使用哪种格式,因此永远不会使用window.main,因为它是不可靠的。如果只有您(即您的主程序)从window.name中读取或写入数据,您可以决定以json格式存储数据并相应地进行存储/检索。但是,如果第三方库也想要存储/检索某些内容,并决定不使用json,而是选择另一种众多序列化格式... 这将意外破坏您的json格式,并肯定会引起麻烦。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接