IFRAME沙箱属性阻止了AJAX调用

时间:2022-12-06 10:54:50

I have an application (http://localhost/MyApp), where some of the parts are rendered through IFRAMES. These iframed parts has no business with the rest of the application's DOM, so I applied the sandbox attribute.

我有一个应用程序(http:// localhost / MyApp),其中一些部分通过IFRAMES呈现。这些iframed部分与应用程序的其余部分没有业务关系,因此我应用了sandbox属性。

The IFRAME is declared like this:

IFRAME声明如下:

<iframe src="/MyApp/en/html/action?id=1" sandbox="allow-forms allow-scripts" seamless="seamless"></iframe>

The iframed page has a button that makes a AJAX call to the same web application, but then rather than a HTTP GET, the browser issues a HTTP OPTIONS that appears as Cancelled, and an error happens:

iframed页面有一个按钮,可以对同一个Web应用程序进行AJAX调用,但是然后浏览器会发出一个显示为已取消的HTTP OPTIONS,而不是HTTP GET,并发生错误:

XMLHttpRequest cannot load http://localhost/MyApp/en/data/action?id=1. Cannot make any requests from null.
Ajax State 0 Error: HTTP 0 

If I add the allow-same-origin to the sandbox attribute, it works.As far as I read here, it was not supposed to affect AJAX calls.

如果我将allow-same-origin添加到sandbox属性,它就可以工作。据我所知,它不应该影响AJAX调用。

Why is this happening? Is considering the path /MyApp/en/html/action as origin of the whole IFRAME and blocking the request to previous levels?

为什么会这样?是考虑将路径/ MyApp / en / html / action作为整个IFRAME的来源并阻止对先前级别的请求?

Cheers.

干杯。

1 个解决方案

#1


22  

The reason it affects Ajax is because Ajax is governed by the Same Origin Policy rules, and when you sandbox it you're effectively telling the browser to treat the iframe contents as if it were from a different origin. Quoting the same article:

它影响Ajax的原因是因为Ajax受同源策略规则的约束,当你沙箱时,你有效地告诉浏览器将iframe内容视为来自不同的来源。引用同一篇文章:

  • Unique origin treatment. All content is treated under a unique origin. The content is not able to traverse the DOM or read cookie information.
  • 独特的原产地治疗所有内容都以独特的来源进行处理。内容无法遍历DOM或读取cookie信息。

This means that even content coming from the same domain is treated with the cross-domain policy, as each IFRAME content will be viewed as a unique origin.

这意味着即使来自同一域的内容也会受到跨域策略的处理,因为每个IFRAME内容都将被视为唯一的来源。

Embedded content is only permitted to display information. No other actions can be done inside the IFRAME that could compromise the hosting website or take advantage of the users’ trust.

嵌入式内容仅允许显示信息。 IFRAME内部无法执行任何可能危及托管网站或利用用户信任的其他操作。

In other words, if you omit the allow-same-origin in the sandbox attribute, it will treat the sandboxed page as belonging to a different domain (in fact, it will treat as having a null origin). Since it doesn't make sense to make Ajax requests to null, sandboxed pages can not make Ajax calls at all (if making them to localhost were allowed they would be indistinguishable from the calls from the parent page, defeating the purpose of sandboxing).

换句话说,如果省略sandbox属性中的allow-same-origin,它会将沙盒页面视为属于不同的域(事实上,它将视为具有空原点)。由于将Ajax请求设置为null没有意义,因此沙盒页面根本无法进行Ajax调用(如果允许它们与localhost一起使用,则它们与来自父页面的调用无法区分,从而无法实现沙盒的目的)。

Additional info

If you try to make an Ajax call to a different domain, it will obviously fail:

如果您尝试对其他域进行Ajax调用,则显然会失败:

<script src="http://code.jquery.com/jquery.min.js"></script>
<script>
    console.log(location.host);
    $.post('https://google.com/',{},function() { });
</script>

However, how it will fail will depend on the sandbox attribute used. If you embed the page above in an iframe with allow-same-origin it will print this to the console:

但是,它将如何失败将取决于所使用的沙箱属性。如果您将上面的页面嵌入带有allow-same-origin的iframe中,它会将其打印到控制台:

localhost
XMLHttpRequest cannot load https://google.com/. Origin http://localhost is not allowed by Access-Control-Allow-Origin.

...and if you embed it without allow-same-origin:

...如果你没有允许同源来嵌入它:

localhost
XMLHttpRequest cannot load https://google.com/. Cannot make any requests from null.

Note that, while both reported location.host as localhost, one considered the origin to be http://localhost while the other considered it to be null (showing the same error message you experienced in your example).

请注意,虽然两者都将local.host报告为localhost,但其中一个认为原点是http:// localhost而另一个认为它是null(显示您在示例中遇到的相同错误消息)。

Reasoning

Why is it so important to block Ajax calls from sandboxed contents from the same domain? As explained in the article:

为什么从同一域中阻止来自沙盒内容的Ajax调用如此重要?正如文章中所解释的那样:

It kind of makes sense that content on the same domain should be safe. The risk here primarily stems from user-generated content that is re-hosted in the IFRAME.

在同一个域上的内容应该是安全的,这是有道理的。此处的风险主要源于在IFRAME中重新托管的用户生成的内容。

Let's make up an example: suppose Facebook decides to allow users post little HTML5 animations in their pages. It stores them in its own servers and, when displaying, sandboxes them as allow-scripts only (because scripts are needed for the animations to work) but leave everything else denied (in particular allow-same-origin, since you don't want user code messing up with the parent page). What would happen if Ajax calls weren't also blocked by default?

让我们举一个例子:假设Facebook决定允许用户在他们的页面中发布少量HTML5动画。它将它们存储在自己的服务器中,并且在显示时,仅将它们作为allow-scripts沙箱(因为动画需要脚本才能工作)但是让其他所有内容都被拒绝(特别是允许同源,因为你不想要用户代码弄乱了父页面)。如果默认情况下也没有阻止Ajax调用会发生什么?

Mallory creates an "animation" that consists of:

Mallory创建了一个“动画”,包括:

  1. Performing an Ajax call to Facebook, using its API (say, Open Graph); the server will happily accept the call, since for all it knows the request came from a page with https://facebook.com as origin.

    使用其API(例如,Open Graph)对Facebook执行Ajax调用;服务器很乐意接受这个电话,因为它知道这个请求来自一个以https://facebook.com为原点的页面。

  2. Create a URI pointing to her own server, with the returned data as query strings, and set it as the src of a picture in the sandboxed page.

    创建指向自己的服务器的URI,返回的数据作为查询字符串,并将其设置为沙盒页面中图片的src。

When Alice visits Mallory profile, and sees the animation, the script above runs:

当Alice访问Mallory配置文件并看到动画时,上面的脚本运行:

  1. The Ajax call runs in Alice's browser, while Alice is logged on; since the server does not know where the call comes from (main page or embedded page) it will do whatever it's asked to - including retrieving personal info.

    Ajax调用在Alice的浏览器中运行,而Alice则登录;由于服务器不知道呼叫来自哪里(主页面或嵌入页面),它将执行任何要求 - 包括检索个人信息。

  2. When the img element is created with Mallory's URI, the browser will attempt to load the "image" normally, since images are exempt from the Same Origin Policy.

    当使用Mallory的URI创建img元素时,浏览器将尝试正常加载“图像”,因为图像不受同源策略的限制。

  3. Since the URI has Alice's private info in the query string, Mallory's server can just save it and return whatever image it wants. Now Mallory has Alice's personal info, and Alice suspects nothing.

    由于URI在查询字符串中包含Alice的私有信息,因此Mallory的服务器可以保存它并返回它想要的任何图像。现在马洛里有爱丽丝的个人信息,而爱丽丝则没有怀疑。

#1


22  

The reason it affects Ajax is because Ajax is governed by the Same Origin Policy rules, and when you sandbox it you're effectively telling the browser to treat the iframe contents as if it were from a different origin. Quoting the same article:

它影响Ajax的原因是因为Ajax受同源策略规则的约束,当你沙箱时,你有效地告诉浏览器将iframe内容视为来自不同的来源。引用同一篇文章:

  • Unique origin treatment. All content is treated under a unique origin. The content is not able to traverse the DOM or read cookie information.
  • 独特的原产地治疗所有内容都以独特的来源进行处理。内容无法遍历DOM或读取cookie信息。

This means that even content coming from the same domain is treated with the cross-domain policy, as each IFRAME content will be viewed as a unique origin.

这意味着即使来自同一域的内容也会受到跨域策略的处理,因为每个IFRAME内容都将被视为唯一的来源。

Embedded content is only permitted to display information. No other actions can be done inside the IFRAME that could compromise the hosting website or take advantage of the users’ trust.

嵌入式内容仅允许显示信息。 IFRAME内部无法执行任何可能危及托管网站或利用用户信任的其他操作。

In other words, if you omit the allow-same-origin in the sandbox attribute, it will treat the sandboxed page as belonging to a different domain (in fact, it will treat as having a null origin). Since it doesn't make sense to make Ajax requests to null, sandboxed pages can not make Ajax calls at all (if making them to localhost were allowed they would be indistinguishable from the calls from the parent page, defeating the purpose of sandboxing).

换句话说,如果省略sandbox属性中的allow-same-origin,它会将沙盒页面视为属于不同的域(事实上,它将视为具有空原点)。由于将Ajax请求设置为null没有意义,因此沙盒页面根本无法进行Ajax调用(如果允许它们与localhost一起使用,则它们与来自父页面的调用无法区分,从而无法实现沙盒的目的)。

Additional info

If you try to make an Ajax call to a different domain, it will obviously fail:

如果您尝试对其他域进行Ajax调用,则显然会失败:

<script src="http://code.jquery.com/jquery.min.js"></script>
<script>
    console.log(location.host);
    $.post('https://google.com/',{},function() { });
</script>

However, how it will fail will depend on the sandbox attribute used. If you embed the page above in an iframe with allow-same-origin it will print this to the console:

但是,它将如何失败将取决于所使用的沙箱属性。如果您将上面的页面嵌入带有allow-same-origin的iframe中,它会将其打印到控制台:

localhost
XMLHttpRequest cannot load https://google.com/. Origin http://localhost is not allowed by Access-Control-Allow-Origin.

...and if you embed it without allow-same-origin:

...如果你没有允许同源来嵌入它:

localhost
XMLHttpRequest cannot load https://google.com/. Cannot make any requests from null.

Note that, while both reported location.host as localhost, one considered the origin to be http://localhost while the other considered it to be null (showing the same error message you experienced in your example).

请注意,虽然两者都将local.host报告为localhost,但其中一个认为原点是http:// localhost而另一个认为它是null(显示您在示例中遇到的相同错误消息)。

Reasoning

Why is it so important to block Ajax calls from sandboxed contents from the same domain? As explained in the article:

为什么从同一域中阻止来自沙盒内容的Ajax调用如此重要?正如文章中所解释的那样:

It kind of makes sense that content on the same domain should be safe. The risk here primarily stems from user-generated content that is re-hosted in the IFRAME.

在同一个域上的内容应该是安全的,这是有道理的。此处的风险主要源于在IFRAME中重新托管的用户生成的内容。

Let's make up an example: suppose Facebook decides to allow users post little HTML5 animations in their pages. It stores them in its own servers and, when displaying, sandboxes them as allow-scripts only (because scripts are needed for the animations to work) but leave everything else denied (in particular allow-same-origin, since you don't want user code messing up with the parent page). What would happen if Ajax calls weren't also blocked by default?

让我们举一个例子:假设Facebook决定允许用户在他们的页面中发布少量HTML5动画。它将它们存储在自己的服务器中,并且在显示时,仅将它们作为allow-scripts沙箱(因为动画需要脚本才能工作)但是让其他所有内容都被拒绝(特别是允许同源,因为你不想要用户代码弄乱了父页面)。如果默认情况下也没有阻止Ajax调用会发生什么?

Mallory creates an "animation" that consists of:

Mallory创建了一个“动画”,包括:

  1. Performing an Ajax call to Facebook, using its API (say, Open Graph); the server will happily accept the call, since for all it knows the request came from a page with https://facebook.com as origin.

    使用其API(例如,Open Graph)对Facebook执行Ajax调用;服务器很乐意接受这个电话,因为它知道这个请求来自一个以https://facebook.com为原点的页面。

  2. Create a URI pointing to her own server, with the returned data as query strings, and set it as the src of a picture in the sandboxed page.

    创建指向自己的服务器的URI,返回的数据作为查询字符串,并将其设置为沙盒页面中图片的src。

When Alice visits Mallory profile, and sees the animation, the script above runs:

当Alice访问Mallory配置文件并看到动画时,上面的脚本运行:

  1. The Ajax call runs in Alice's browser, while Alice is logged on; since the server does not know where the call comes from (main page or embedded page) it will do whatever it's asked to - including retrieving personal info.

    Ajax调用在Alice的浏览器中运行,而Alice则登录;由于服务器不知道呼叫来自哪里(主页面或嵌入页面),它将执行任何要求 - 包括检索个人信息。

  2. When the img element is created with Mallory's URI, the browser will attempt to load the "image" normally, since images are exempt from the Same Origin Policy.

    当使用Mallory的URI创建img元素时,浏览器将尝试正常加载“图像”,因为图像不受同源策略的限制。

  3. Since the URI has Alice's private info in the query string, Mallory's server can just save it and return whatever image it wants. Now Mallory has Alice's personal info, and Alice suspects nothing.

    由于URI在查询字符串中包含Alice的私有信息,因此Mallory的服务器可以保存它并返回它想要的任何图像。现在马洛里有爱丽丝的个人信息,而爱丽丝则没有怀疑。