跨域哈希改变通信

4
请考虑以下两个域:domain1.com和domain2。
从domain1打开指向domain2的iframe。
现在,我想让这些页面进行通信,并成功地通过在两个域上应用哈希更改事件侦听器来实现了这一点。
通过这种方式,在父窗口(domain1)中的哈希将触发,如果domain2使用新哈希调用parent.location。此外,如果我从父级更改其src属性到新哈希,则iframe中的哈希更改事件会触发。
这很不错!
在这里遇到了麻烦:
浏览器中的“后退”和“前进”功能出现问题。简而言之,通过创建两个哈希实例,浏览器的后退按钮必须单击两次才能更改父哈希,因为它必须先经过iframe的哈希。
如何在不影响历史对象的情况下与跨域iframe进行双向通信?
谢谢!

我想到了一种可能的(丑陋的!)解决方案:我可以在domain1上附加一个指向domain2的脚本,如下所示:<script type="text/javascript" src="http://domain2.com/#whatever=hash&i=want&to=parse"></script>。然后,这个JS文件将设置一个cookie,另一个在domain2上的JS文件将监听其更改。当cookie发生变化时,就意味着有些东西已经改变了,你需要相应地采取行动。对于这种方法有什么想法吗? - John
这可能不起作用。每次都需要一个请求。 - John
2个回答

7
使用easyXDM,它是一个JavaScript库,可以为您完成所有繁重的工作,使您能够在所有浏览器中进行跨域通信和RPC,包括IE6。
这不会在任何当前浏览器(甚至IE6)中使用HashTransport,因此不会更改历史记录。
您将找不到比这更好的东西...
您可以在Script Junkie article中了解其一些内部工作原理,或者直接转到github上的readme

嗨,肖恩。哇,真是令人印象深刻的工作。我正在实现它!会让你知道它对我有什么作用。到目前为止,谢谢你,伙计。 - John
顺便问一下,哪些浏览器会使用HashTransport?需要阻止它们,因为它会干扰我现有的哈希实现,影响书签和导航。 - John
谢谢,感激不尽。在自述文件中有一个列表列出了所有支持的“一流”浏览器,这些浏览器将不使用HashTransport。 - Sean Kinsey
啊,好的。我现在已经实现了它。再次感谢!完美地工作。 - John
很酷 :) 你使用它时有遇到任何问题吗?README 文件足够清晰明了吗? - Sean Kinsey

2
跨域通信的另一种技术是滥用window.name。它需要一个iframe最初具有相同域名的src,然后您移动到设置window.name的另一个域,然后退回到原始源(在历史记录中后退)。这个想法是window.name除非明确设置,否则不会改变,这意味着您可以跨域传输window.name数据。
更多详细信息请参见以下链接:
- http://skysanders.net/subtext/archive/2010/10/11/leveraging-window.name-transport-for-secure-and-efficient-cross-domain-communications.aspx
- http://jectbd.com/?p=611 请确保选择避免在IE中出现点击声音的实现方式。
不幸的是,它仍会影响您的历史记录,但会向前迈一步,然后返回到历史记录点。一个很大的好处是,您不必解析和编码URI字符串,而可以直接使用JSON。
使用JSON库进行示例:Using JSON lib for example
// access window.name from parent frame
// note: only when iframe stepped back to same domain.
var data = JSON.parse( iframe.contentWindow.name );

// set child frame name
// note: only when iframe stepped back to same domain.
iframe.contentWindow.name = JSON.stringify( {
    foo : "bar"
} ); // to JSON string

// set own name ( child frame )
window.name = JSON.stringify( {
    foo : "bar"
} ); // to JSON string

cookie技术也是可行的,对于这两种技术,如果你想避免历史记录的更改但仍需要http请求,则需要在目标iframe中执行ajax请求。
所以:
1.使用cookie或window.name技术将数据发送到iframe x;
2.在iframe x中使用轮询器获取数据;
3.在iframe x中执行ajax请求;
4.使用cookie或window.name技术将数据发送回iframe y;
5.在iframe y中使用轮询器获取数据;
6.完成hokey pokey。
任何页面刷新(http请求)或url更改都会更新历史记录(除了旧版或所有IE版本),因此需要更多的代码。

感谢您详细的回答!非常感激。但是,您确定这可以跨域工作吗?当我尝试从iframe访问window.name时,我得到了以下错误:Error: Permission denied for http://domain1.com to get property Window.name from http://domain2.com。 - John
你看了一下,你使用的是哪个浏览器? - BGerrissen
Firefox 3.6.12 在 MacOSX 上。在 Chrome 7 中也会出现以下问题:尝试使用不安全的 JavaScript 访问 URL 为 http://domain1.com 的框架,而该框架来自 URL 为 http://domain2.com 的框架。域、协议和端口必须匹配。 - John
非常抱歉,这个技术还有一些细节需要注意。请查看文章链接并更新我的回答。无论如何,任何技术都会感觉像是一个hack =( - BGerrissen
没问题。根据Sean发布的Script Junkie文章,window.name在新版本的浏览器中将无法使用。我会选择easyXDM框架。非常感谢您的时间和帮助! - John

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