html5 javascript- 如何捕捉尝试从沙盒 iframe 中启动导航?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21564860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 21:12:21  来源:igfitidea点击:

html5 javascript- How to catch attempt to initiate navigation out of sandboxed iframe?

javascripthtmliframesandbox

提问by Tom

I have an sandboxed iframe that doesn't allow changing location:

我有一个不允许更改位置的沙盒 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>

If the iframe tries to unframe itself or change location I see a blank page because the browser stops the iframe's operation. This is the log from Chrome:

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

Unsafe JavaScript attempt to initiate navigation for frame with URL 'http://example.com' from frame with URL 'http://otherdomaian.com'. The frame attempting navigation of the top-level window is sandboxed, but the 'allow-top-navigation' flag is not set.

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

That is great but I want to catch this so if it happens I'll move to the next iframe. So how do I catch this attempt?

太好了,但我想抓住这个,所以如果发生了,我会转移到下一个 iframe。那么我如何抓住这个尝试呢?

EDIT:

编辑:

I added a jsfiddle code(check the error in the console log)

我添加了一个jsfiddle 代码(检查控制台日志中的错误)

I also tried to listen for an event with no success:

我还尝试侦听一个事件,但没有成功:

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

回答by Jeremy Hert

I am new here so I don't have enough reputation to comment on answers and I apologize if I am doing this wrong, but the accepted solution will unfortunately not be able to accomplish what you are looking for.

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

I was able to demonstrate what I mean by having the script from the JSFiddle above run once the DOM is ready (there will be no alert but still an error in the console). Here's a little more detail on what happens currently with that fiddle:

我能够通过在 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!');
}

The exception that is being caught has nothing to do with the iframe, it is actually a type error from trying to set the srcproperty on a nullvalue.

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

What you really want to do is catch the error insideof the iframe (when the sandboxed script tries to access window.top), but this is not possible because of the Same-origin policy. Btw, setting the "allow-same-origin"sandbox flag only has any effect when the iframe content is being served from the same originas the top level document. E.g. as soon as the srcor locationof the iframe is changed to a different origin, there's no way to touch anything inside.

您真正想要做的是捕获iframe内部的错误(当沙盒脚本尝试访问时window.top),但由于同源策略,这是不可能的。顺便说一句,设置"allow-same-origin"沙箱标志仅在 iframe 内容origin与顶级文档相同时才有效。例如,一旦iframe的srcorlocation更改为不同的origin就无法触及内部的任何内容

There are ways to communicate across iframeboundaries, such as with window.postMessageor the older and hackier way of using the iframe's location.hash, but I am assuming you can't affect the source of the page going into your iframe. (A nice developer would of course be open to suggestions and see that a feature like this could be useful.)

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

The only way that I was able to catch this error without violating any browser security policies was to set the allow-top-navigationsandbox flag and then use the window.onbeforeunloadhandler in the top level document to catch the navigation attempt from the child iframe. I would never recommend this because the user experience is awful. There is no way to prevent the navigation without prompting the user about whether they want to leave the page or not. Proof of concept below:

我能够在不违反任何浏览器安全策略的情况下捕获此错误的唯一方法是设置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>

So unfortunately I can't find any ways to do this nicely in current browser implementations without help from your 3rd party content developer. I read some interesting things in the HTML5 spec that might allow us to do things like this in the future (and am unfortunately maxed out on my number of links I can insert here), so I would keep an eye out as things progress.

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

回答by evergreen

Example:

例子:

An with extra restrictions:

有额外限制:

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

the sandbox attribute is supported in Internet Explorer 10, Firefox, Chrome, and Safari.

沙箱属性在 Internet Explorer 10、Firefox、Chrome 和 Safari 中受支持。

Note: The sandbox attribute is not supported in Internet Explorer 9 and earlier versions, or in Opera.

注意:Internet Explorer 9 及更早版本或 Opera 不支持沙箱属性。

Definition and Usage

定义和用法

If specified as an empty string (sandbox=""), the sandbox attribute enables a set of extra restrictions for the content in the inline frame.

The value of the sandbox attribute can either be an empty string (all the restrictions is applied), or a space-separated list of pre-defined values that will REMOVE particular restrictions.

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

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

Differences Between HTML 4.01 and HTML5

HTML 4.01 和 HTML5 之间的差异

The sandbox attribute is new in HTML5.

sandbox 属性是 HTML5 中的新属性。

Syntax

句法

<iframe sandbox="value">

Attribute Values

属性值

  1. "" => Applies all restrictions below
  2. allow-same-origin => Allows the iframe content to be treated as being from the same origin as the containing document
  3. allow-top-navigation => Allows the iframe content to navigate (load) content from the containing document
  4. allow-forms => Allows form submission
  5. allow-scripts => Allows script execution
  1. "" => 应用以下所有限制
  2. allow-same-origin => 允许将 iframe 内容视为与包含文档来自同一来源
  3. allow-top-navigation => 允许 iframe 内容从包含的文档中导航(加载)内容
  4. allow-forms => 允许表单提交
  5. allow-scripts => 允许脚本执行

javascript: is a kind of weird URI protocol. It works in some contexts, like , but not all - for instance, a window's location can not be set to such a URI. (While you can assign a javascript: URI to window.location as a really roundabout way of running a script, the window's location doesn't stay set to that value.)

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

To write content into an IFRAME, get a reference to the frame's document and write to it. Doing so will require that you set the allow-same-origin sandbox flag.

要将内容写入 IFRAME,请获取对框架文档的引用并将其写入。这样做将要求您设置允许同源沙箱标志。

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

Live example:http://jsfiddle.net/wUvrF/1/

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

回答by Andrew Fader

You can now do this with allow-top-navigation-by-user-activation

你现在可以用 allow-top-navigation-by-user-activation