IFRAME沙箱属性阻止了AJAX调用

vto*_*ola 11 ajax iframe html5 sandbox same-origin-policy

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

IFRAME声明如下:

<iframe src="/MyApp/en/html/action?id=1" sandbox="allow-forms allow-scripts" seamless="seamless"></iframe>
Run Code Online (Sandbox Code Playgroud)

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

XMLHttpRequest cannot load http://localhost/MyApp/en/data/action?id=1. Cannot make any requests from null.
Ajax State 0 Error: HTTP 0 
Run Code Online (Sandbox Code Playgroud)

如果我添加allow-same-originsandbox属性,它works.As据我读到这里,它不应该影响AJAX调用.

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

干杯.

mgi*_*nbr 24

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

  • 独特的原产地治疗 所有内容均以独特的来源进行处理.内容无法遍历DOM或读取cookie信息.

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

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

换句话说,如果你忽略allow-same-originsandbox属性,它将把沙盒页属于不同的域(事实上,它会将为具有null原点).由于向Ajax请求没有意义null,沙盒页面根本无法进行Ajax调用(如果localhost允许它们被允许,它们将与来自父页面的调用无法区分,从而无法实现沙盒的目的).

附加信息

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

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

但是,它将如何失败将取决于所使用的沙箱属性.如果上面嵌入在网页中的iframe使用allow-same-origin将打印此控制台:

localhost
XMLHttpRequest cannot load https://google.com/. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
Run Code Online (Sandbox Code Playgroud)

......如果你没有 嵌入它allow-same-origin:

localhost
XMLHttpRequest cannot load https://google.com/. Cannot make any requests from null.
Run Code Online (Sandbox Code Playgroud)

需要注意的是,虽然都报告location.hostlocalhost,一个被认为起源是http://localhost,而其他认为它null(显示在您的例子经历了同样的错误消息).

推理

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

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

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

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

  1. 使用其API(例如,Open Graph)对Facebook执行Ajax调用; 服务器将很乐意接受该呼叫,因为它知道所有请求来自具有https://facebook.com原始的页面.

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

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

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

  2. img使用Mallory的URI创建元素时,浏览器将尝试正常加载"图像",因为图像不受同源策略的约束.

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

  • 我想指出,将allow-same-origin标记添加到沙箱属性实际上并不会将外来源作为相同的原点处理.它只使浏览器处理这个iframe,因为普通的iframe将由同一个原始策略处理.因此,如果将此属性应用于外部域页面,它仍然无法访问主页面的DOM.仅当您将其应用于同一域(或域策略标头允许的任何其他域)上的URL时,该页面才能访问您的DOM或向您的域发出AJAX请求. (5认同)