【问题标题】:Event triggering from iframe从 iframe 触发的事件
【发布时间】:2014-05-07 16:00:15
【问题描述】:

我正在将第三方照片上传服务与我的应用程序集成。所以我通过 iframe 将它加载到我的页面中。

当上传服务完成上传我的照片后,它可以触发某些事件到我的父页面,即:

parent.$('body').trigger('photoUpload.complete');

或者它触发父页面中的一个功能,即:

window.parent.reloadParentPage();

无论如何,我都会在我的 chrome 控制台中收到此警告:

Uncaught SecurityError: Blocked a frame with origin "https://photoupload.com" from accessing a frame with origin "https://website.com".

我意识到这是一个安全问题,如此处所述:

http://www.w3.org/TR/2008/WD-access-control-20080912/

所以我想启用源 https://photoupload.com 访问我的网站。我在我的控制器中这样做了:

after_filter :set_access_control_headers

然后方法:

def set_access_control_headers 
  headers['Access-Control-Allow-Origin'] = "https://photoupload.com" 
  headers['Access-Control-Request-Method'] = '*' 
end

请注意https://photoupload.com 是照片上传服务,https://website.com 是我的网站。 (例如清酒的虚构名称),但它们都托管在 heroku 上。

我该如何进行这项工作?

看到类似的问题,人们在这方面取得了成功:

Triggering a jQuery event from iframe

更新

也许更好的问题是,我应该在哪个应用程序中设置标题?我假设在我的应用中?

更新二

有没有更好的方法来做到这一点?从 iframe 向父页面发送 action/event/something,以便父页面可以以某种方式做出反应

【问题讨论】:

  • 如果您使用理智/简短/有意义的域名,将会有很大帮助。 Heroku 不是这里的原因,所以这些信息没有给我们任何信息。也就是说,您应该在父页面中设置标题,允许从 iframe 访问。您可以先尝试在两侧设置Access-Control-Allow-Origin: *,看看是否可以解决问题。
  • @MichaelSzyndel 感谢您对迈克尔的回复。我编辑了这个问题,希望这些名字现在更有意义。 Website.com 是我的网站,而 photoupload.com 是我在 iframe 中嵌入的 url。一个问题,为什么我需要在两边都允许原点?
  • 你可能不知道,但它是一个很好的开始。如果这可行,那么您可以尝试将其从一侧(iframe 内容)移除并重新测试。我怀疑浏览器的行为在这里会有很大的不同,所以自上而下的方法对我来说更有意义。
  • @MichaelSzyndel 好的,谢谢,我会尝试一下,看看是否可行,是否有更好的方法来完成我想要完成的事情。以某种方式让父页面知道 iframe 中发生了什么事情。我尝试在父页面上调用函数或调用父页面上的侦听器观察到的事件
  • 访问控制标头不会为您执行此操作 - 正如 Barmaley.exe 指出的那样,它们用于 XHR 请求,而不是窗口间通信 - 您需要使用 postMessage 或替代方法。好消息是您可以修改服务 - 我的回答应该对您有用。

标签: javascript jquery ruby-on-rails iframe


【解决方案1】:

只要您不必支持 IE6 或 IE7,在 iframe 与其父级之间发送跨域消息的首选方式是使用window.postMessage(...)

既然你有能力修改上传服务,你应该让它调用这样的东西:

window.parent.postMessage('photoUpload.complete', 'https://website.com');

(第二个参数可以设置为 '*' 以允许 iframe 发送消息,而不管包含页面的域如何,但这相应地不太安全 - 尽管没有发送实际数据,但可能与您的情况无关) .

你的网站会使用类似的东西

if (!window.addEventListener) {
    // IE8 support (could also use an addEventListener shim)
    window.attachEvent('onmessage', handleMessage);
} else {
    window.addEventListener('message', handleMessage, false);
}

function handleMessage(event) {
  // check where the message is coming from - may be overkill in your case
  if (event.origin==='https://photoupload.org') {
    // check event type - again probably not required
    if (event.data==='photoUpload.complete') {
      // do your thing
    }
  }
}

如果你想将消息从外部页面发送回 iframe,它基本上是相同的设置,但你发送的是:

iframe.contentWindow.postMessage(...)

如果需要 IE7 或 IE6 支持,则不支持 postMessage(),但您可以使用 http://easyxdm.net/wp/ 之类的东西

【讨论】:

  • 感谢您的回复。我不需要对 IE6 和 IE7 的支持。但是从 IE 8 起,addEventListener 的替代品是什么?
  • 我已经添加了 IE8 代码。 IE9 及更高版本应使用 addEventListener。 IE8 在更新后的代码中使用 attachEvent。
【解决方案2】:

我想这条线应该也可以

window.parent.$(window.parent.document).trigger('photoUpload.complete');

解释:在你的代码中 parent.$('body').trigger('photoUpload.complete'); “body”指的是 iframe 主体,而不是父窗口主体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 2011-07-13
    相关资源
    最近更新 更多