【问题标题】:html5 javascript- How to catch attempt to initiate navigation out of sandboxed iframe?html5 javascript-如何捕获从沙盒 iframe 中启动导航的尝试?
【发布时间】:2014-03-01 03:39:54
【问题描述】:

我有一个不允许更改位置的沙盒 iframe:

<iframe sandbox="allow-forms allow-popups allow-pointer-lock allow-same-origin allow-scripts" class="iframe visible" src="thesource.html" width="100%" scrolling="auto" frameborder="0"></iframe>

如果 iframe 尝试自行取消框架或更改位置,我会看到一个空白页面,因为浏览器停止了 iframe 的操作。这是来自 Chrome 的日志:

不安全的 JavaScript 尝试从 URL 为“http://otherdomaian.com”的框架启动对 URL 为“http://example.com”的框架的导航。尝试导航顶级窗口的框架已被沙盒化,但未设置“allow-top-navigation”标志。

这很好,但我想抓住它,所以如果发生这种情况,我会转到下一个 iframe。那么我该如何捕捉这种尝试呢?

编辑:

我添加了jsfiddle code(检查控制台日志中的错误)

我也尝试监听一个没有成功的事件:

document.addEventListener('error', receiveMessage, true);
function receiveMessage(error) {
    alert("iframe tried to unframe itself");
}

【问题讨论】:

  • 这是否包括有人点击一个链接并且它的目标设置为_parent_top的情况?

标签: javascript html iframe sandbox


【解决方案1】:

例子:

有额外限制的:

<iframe src="demo_iframe_sandbox.htm" sandbox=""></iframe>

Internet Explorer 10、Firefox、Chrome 和 Safari 支持 sandbox 属性。

注意:Internet Explorer 9 不支持沙盒属性 和更早的版本,或在 Opera 中。

定义和用法

如果指定为空字符串 (sandbox=""),则沙盒属性 为内联内容启用一组额外的限制 框架。

沙盒属性的值可以是空字符串(所有 应用了限制),或以空格分隔的预定义列表 将删除特定限制的值。

HTML 4.01 和 HTML5 的区别

沙盒属性是 HTML5 中的新属性。

语法

<iframe sandbox="value">

属性值

  1. "" => 应用以下所有限制
  2. allow-same-origin => 允许将 iframe 内容视为与包含文档来自同一来源
  3. allow-top-navigation => 允许 iframe 内容从包含的文档中导航(加载)内容
  4. allow-forms => 允许提交表单
  5. allow-scripts => 允许脚本执行

javascript: 是一种奇怪的 URI 协议。它适用于某些上下文,例如,但不是全部 - 例如,窗口的位置不能设置为这样的 URI。 (虽然您可以将 javascript: URI 分配给 window.location 作为运行脚本的真正迂回方式,但窗口的位置不会保持设置为该值。)

要将内容写入 IFRAME,请获取对框架文档的引用并将其写入。这样做需要您设置 allow-same-origin 沙箱标志。

<iframe id="myframe" sandbox="allow-scripts allow-same-origin" src="about:blank"></iframe>

<script>
    var frame = document.getElementById("myframe");
    var fdoc = frame.contentDocument;

    fdoc.write("Hello world"); // or whatever
</script>

现场示例: http://jsfiddle.net/wUvrF/1/

【讨论】:

    【解决方案2】:

    我是新来的,所以我没有足够的声誉来评论答案,如果我做错了,我深表歉意,但遗憾的是,公认的解决方案将无法完成您正在寻找的内容。

    一旦 DOM 准备好,我就可以通过运行上面 JSFiddle 中的脚本来证明我的意思(不会有警报,但控制台中仍然会出现错误)。以下是有关该小提琴当前发生的情况的更多详细信息:

    // running with the No wrap - in <head> option
    var frame = document.querySelector('iframe'); // null, the iframe isn't there yet
    try {
        frame.src="http://wedesignthemes.com/themes/redirect.php?theme=wedding";
    } catch(e) {
        // TypeError here, no hints about the iframe :(
        alert('Error!');
    }
    

    被捕获的异常与 iframe 无关,它实际上是尝试在 null 值上设置 src 属性的类型错误。

    您真正想要做的是捕获 iframe 的错误inside(当沙盒脚本尝试访问window.top 时),但由于Same-origin policy,这是不可能的。顺便说一句,设置 "allow-same-origin" 沙盒标志仅在 iframe 内容从与顶级文档相同的 origin 提供时才有任何效果。例如。只要 iframe 的 srclocation 更改为不同的 originthere's no way to touch anything inside

    有多种方法可以跨越iframe 边界进行通信,例如使用window.postMessage 或使用iframe 的location.hash 的更老和更老套的方式,但我假设您不能影响进入的页面的来源你的 iframe。 (一个优秀的开发人员当然会乐于接受建议,并认为这样的功能可能很有用。)

    在不违反任何浏览器安全策略的情况下,我能够捕获此错误的唯一方法是设置 allow-top-navigation 沙盒标志,然后使用顶级文档中的 window.onbeforeunload 处理程序来捕获来自孩子的导航尝试iframe。我永远不会推荐这个,因为用户体验糟糕。如果不提示用户是否要离开页面,就无法阻止导航。下面的概念证明:

    <iframe id="myframe" sandbox="allow-scripts allow-top-navigation"></iframe>
    <script>
      var url = "http://wedesignthemes.com/themes/redirect.php?theme=wedding",
          frame = document.getElementById("myframe"),
          listener;
      listener = window.addEventListener("beforeunload", function(e) {
          e.preventDefault();
          e.stopImmediatePropagation();
          // The iframe tried to bust out!
          window.removeEventListener("beforeunload", listener);
          return "This is unavoidable, you cannot shortcut a " +
                 "navigation attempt without prompting the user";
      });
      frame.src = url;
    </script>
    

    很遗憾,如果没有您的第 3 方内容开发人员的帮助,我无法在当前的浏览器实现中找到任何方法来很好地做到这一点。我在 HTML5 规范中读到了一些有趣的东西,它们可能允许我们在未来做这样的事情(不幸的是,我可以在这里插入的链接数量已经达到极限),所以我会密切关注事情的进展。

    【讨论】:

    • 非常好的文章。这应该是公认的答案。
    • 我已经用大红旗更新了我的答案,所以人们不要使用它。感谢您发现并指出这一点!
    【解决方案3】:

    您现在可以使用 allow-top-navigation-by-user-activation 完成此操作

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      • 2014-03-02
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      • 2012-08-09
      相关资源
      最近更新 更多