我有一个应用程序(http://localhost/MyApp),其中一些部分通过iFrame渲染。这些iframed部分与应用程序DOM的其余部分没有任何关系,因此我应用了sandbox属性
IFRAME声明如下:
<;iframe src=”https://stackoverflow.com/MyApp/en/html/action?id=1“sandbox=“允许表单允许脚本”无缝=“无缝”></iframe>;
iframed页面有一个按钮,用于对同一web应用程序进行AJAX调用,但浏览器发出的不是HTTP GET,而是HTTP选项,显示为已取消,出现错误:
无法加载XMLHttpRequesthttp://localhost/MyApp/en/data/action?id=1. 无法从null发出任何请求。
Ajax状态0错误:HTTP 0
如果我将allow same origin添加到sandbox属性中,它就可以工作了
为什么会这样?是否将路径/MyApp/en/html/action视为整个IFRAME的来源,并将请求阻止到以前的级别
干杯
它影响Ajax的原因是Ajax受同一源策略规则的控制,当您对其进行沙箱处理时,实际上是在告诉浏览器将iframe内容视为来自不同的源。引用同一条:
- 唯一来源处理。所有内容都在唯一来源下处理。内容无法遍历DOM或读取cookie信息
这意味着,即使来自同一域的内容也将使用跨域策略处理,因为每个IFRAME内容都将被视为唯一的来源
嵌入式内容仅允许显示信息。在IFRAME中不能执行任何其他可能危害托管网站或利用用户信任的操作
换句话说,如果在沙盒属性中省略允许相同来源,它会将沙盒页面视为属于不同的域(事实上,它将视为具有null来源)。由于将Ajax请求设置为null没有意义,沙盒页面根本无法进行Ajax调用(如果允许将它们设置为localhost,则它们将无法与父页面的调用区分开来,从而无法实现沙盒的目的)
附加信息
如果尝试对其他域进行Ajax调用,显然会失败:
<;脚本src=";http://code.jquery.com/jquery.min.js"&燃气轮机</脚本>;
<;脚本>;
console.log(location.host);
$.post($)https://google.com/“,{},函数(){});
</脚本>;
但是,如何失败取决于使用的沙盒属性。如果将上面的页面嵌入到带有允许相同原点的iframe中,它会将其打印到控制台:
localhost
无法加载XMLHttpRequesthttps://google.com/. 起源http://localhost 访问控制允许原点不允许。
…如果您在不使用的情况下嵌入它,则允许使用相同的源代码:
localhost
无法加载XMLHttpRequesthttps://google.com/. 无法从null发出任何请求。
请注意,虽然两者都将location.host报告为localhost,但其中一个认为原点是http://localhost,而另一个认为它是null(显示您在示例中遇到的相同错误消息)
推理
为什么阻止来自同一域的沙盒内容的Ajax调用如此重要?如文章所述:
在某种意义上,相同域上的内容应该是安全的。这里的风险主要来自重新托管在IFRAME中的用户生成的内容
让我们举个例子:假设Facebook决定允许用户在他们的页面上发布HTML5动画。它将它们存储在自己的服务器中,并且在显示时,沙盒将它们作为仅允许脚本(因为动画工作需要脚本),但其他所有内容都被拒绝(特别是允许同源,因为您不希望用户代码弄乱父页面)。如果默认情况下Ajax调用没有被阻止,会发生什么
马洛里创造了一个;动画";这包括:
-
使用Facebook的API(比如opengraph)执行对Facebook的Ajax调用;服务器将愉快地接受调用,因为据它所知,请求来自
https://facebook.com作为原点 -
创建一个指向她自己的服务器的URI,返回的数据作为查询字符串,并将其设置为沙盒页面中图片的
src
当Alice访问Mallory profile并看到动画时,上面的脚本将运行:
-
当Alice登录时,Ajax调用在Alice的浏览器中运行;由于服务器不知道呼叫来自何处(主页或嵌入页面),它将执行任何要求执行的操作,包括检索个人信息
-
当使用Mallory的URI创建
img元素时,浏览器将尝试加载;“图像”;通常情况下,因为图像不受同源策略的约束 -
由于URI在查询字符串中包含Alice的私有信息,Mallory的服务器可以保存它并返回它想要的任何图像。现在马洛里掌握了爱丽丝的个人信息,爱丽丝对此毫无怀疑