【问题标题】:window.name as a data transport: a valid approach?window.name 作为数据传输:一种有效的方法?
【发布时间】:2012-05-21 00:33:48
【问题描述】:

概述和原始问题

window.name 是一只有趣的野兽。 MDN 的描述暗示了最初的意图:

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

所以,这意味着我们可以在这个窗口中打开控制台,然后写:

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

...然后让它通过弹出窗口阻止程序,它应该在名为“el goog”的窗口中打开 google.com。由于同源策略,我无法访问winname 属性,但是如果我在新窗口中打开控制台并输入name,我将得到"el goog"

如果我将窗口发送回我打开它的域(在本例中为 stackoverflow.com),我可以获得name 属性,并且它没有改变。

win.location.replace(location.href);
win.name; // "el goog"

这意味着我们可以通过设置窗口的name 属性来拥有一种跨域会话存储。

如果 google.com 在窗口被发送回原始域之前更改 window.name 的值,我们将看到新值而不是“el goog”。这可以用作跨域数据传输,在实用性上类似于 JSONP 或 CORS。

我进行了一些搜索以尝试找到更多信息,显然道场thinks it's legit 是一种传输方式。不过,不知何故,这并不能完全让我放心。所以我的问题是,是否有信誉良好的网站使用window.name 作为数据传输?我认为它很容易被发现,因为他们的文档会说“为 JSONP 的查询字符串添加'回调',或为 window.name 添加'whatever',”但我'从来没有见过这样的事情。有人真的在野外发现过这个吗?


替代问题

可能没有人真正使用这种技术;如果这是真的,那么(正如 Rob W 指出的那样)上面的问题是无法回答的。所以,我的另一个问题是,这种方法有什么问题?这可能有助于解释为什么它没有真正被采用。

在我看来,与 JSONP 相比,这种方法至少有两个好处。

  • 使用 JSONP,您可以信任来自外国的脚本在您的域上运行。使用window.name,恶意站点包含的任何脚本都将在其自己的域上运行。

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

有什么缺点?


示例实现

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

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);

});​

我已经设置了一个小提琴来测试它here。 它使用this script 作为测试服务器。

这里有一个稍长的例子,可以发出 POST 请求:http://jsfiddle.net/n9Wnx/2/


总结

据我所知,window.name 还没有流行起来作为数据传输。我想知道我的看法是否准确(因此是原始问题),如果是,我想知道为什么会出现这种情况。我列出了window.name 似乎优于 JSONP 的一些优点。任何人都可以找出一些可能阻碍采用这种技术的缺点吗?

更重要的是,谁能给我一个充分的理由为什么我不应该使用winow.name 作为数据传输?

【问题讨论】:

  • @RobW 类似“是的,blahboop.com API 将使用 JSONP 或 window.name...响应请求”,其中 blahboop.com 是人们实际使用的东西。一些东西可以为这个想法增加一些合法性。我很确定我可以处理实施,但我认为看到使用该技术的合法网站可能会说明可靠性(至少该行为将来不太可能被删除)
  • 知道某个站点使用了某种技术并不会使该方法更加强大/有效。假设答案是“谷歌使用这种技术”。是什么赋予了?如果将问题表述为“......任何陷阱/可能的问题?”,这个问题会更回答
  • @RobW 我想过这个问题,但感觉我基本上是在说“为什么没有人使用这种技术”,我不确定是否真的没有人使用它,所以我想我会先问这个问题。
  • @MrChrisRodriguez 听起来这很适合您正在做的事情,但您可能还想查看postMessage

标签: javascript same-origin-policy


【解决方案1】:

更重要的是,谁能给我一个充分的理由为什么我不应该使用 winow.name 作为数据传输?

虽然window.name 在跨域更改传输数据时可以成为真正的救星,但它不能用作真正的通用数据传输机制的原因是由于缺少存储和检索数据的 api。例如localStorage 提供setItemgetItem。这样的 api 对于从值的实际存储方式中抽象出来并防止格式冲突(如果您身边运行的不同库以不同格式存储时会出现这种情况)是必要的。

据我所知,window.name 并没有流行起来作为数据传输。我想知道我的看法是否准确(因此是原始问题),如果是,我想知道为什么会这样。

由于window.name 没有提供这样的存储/检索抽象层——如我上面所述——第三方库无法知道在window.main 中存储数据时使用哪种格式,因此永远不会使用window.main因为它不可靠。如果您(即您的主程序)是唯一一个读取或写入window.name 的人,您可以决定以 json 格式存储数据并相应地存储/检索。但是,如果第 3 方库也想存储/检索某些内容并决定不使用 json 而是使用另一个 numerous serialization formats... 这会意外破坏您的 json 格式并肯定会造成麻烦。

【讨论】:

    【解决方案2】:

    window.name 作为一种传输方式并不是特别好,因为(AFAIK)它在更改时不会触发任何事件。因此,尝试使用 window.name 作为双向通信通道的应用程序必须轮询它以获取更新。

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

    【讨论】:

    • 有趣,我只是在想事件的事情。 ISTM,myIframe.onload = finishRequest; myIframe.src='somehost.com/api/?id=123' 之类的东西应该可以正常工作......
    • 我在问题中添加了一个基于事件的示例。那是你的想法吗?你能想到的还有什么其他的东西会使它不适合数据传输吗?
    • @AwalGarg 您不能将事件发送到另一个来源的窗口。
    猜你喜欢
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-29
    • 2012-03-05
    相关资源
    最近更新 更多