我正在尝试创建一个内部有JS fire但不能访问父文档的iframe。目标是实现一个简单的实现,而不是包含任何特殊的库。我发现HTML5 Sandbox attribute是一个可行的解决方案;然而,证明很难同时沙盒化iframe 和将JS放入其中。
我试过了:
srcdoc
属性设置HTML(例如<iframe sandbox="allow-scripts" srcdoc="<body><script src='sample1.js'></script><script src='sample2.js'></script></body>"></iframe>
)根据here src
属性设置HTML(例如<iframe sandbox="allow-scripts" src="javascript:"<html><body><script src='sample1.js'></script><script src='sample2.js'></script></body></html>""></iframe
)这在Firefox 38.0.5(Mac OS X Yosemite)中不起作用,但适用于Chrome 43&amp; Safari 8.0.4 ...&#34;无法在Firefox&#34;意味着它确实允许sample2.js将<span></span>
添加到iframe DOM,但它不会设置span的innerText;因此,它不能按预期工作。 我创建了一个JSFiddle,但它没有提供正确的行为,因为它位于嵌套的iframe中......我设置了一个简单的页面并在我的localhost上进行测试。这是我用于测试的代码:
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
</head>
<body>
<!-- Case #2 ~ Does not work in IE -->
<iframe srcdoc="<body><script src='sample1.js'></script><script src='sample2.js'></script></body>" sandbox="allow-scripts">
</iframe>
<!-- Case #3 ~ Does not work in Firefox -->
<iframe src="javascript:"<html><body><script src='sample1.js'></script><script src='sample2.js'></script></body></html>"" sandbox="allow-scripts">
</iframe>
<!-- Case #4 ~ Sandbox maybe not applied? -->
<script>
var i = document.createElement('iframe');
i.src = "about:blank";
i.id = "bryce_iframe";
document.body.appendChild(i);
// iframe added to page
var j = document.getElementById('bryce_iframe').contentDocument;
j.open();
var js = "<html><head>" +
"<scr"+"ipt>window.top.document.getElementById('bryce_iframe').sandbox = 'allow-scripts';</scr"+"ipt>" +
"</head><body>" +
"<p>Hi</p>" +
"<scr"+"ipt>" +
"var p = document.createElement('p');" +
"p.innerText = 'should throw error'; console.log(p);" +
"window.top.document.body.appendChild(p);" +
"</scr"+"ipt>" +
"</body></html>";
// "window.top.document.body.appendChild(p)" should throw an error because of sandbox
j.write(js);
j.close();
</script>
</body>
</html>
我的sample1.js文件如下所示:
var s = document.createElement('span');
s.innerText = "hi";
window.top.document.body.appendChild(s);
我的sample2.js文件如下所示:
var txt = "this doesn't try to break out of iframe";
var s = document.createElement('span');
s.innerText = txt;
document.onload=document.body.appendChild(s);
我几周来一直在寻找有关这个问题的有用资源。如果有另一组眼睛和我一起看它会很棒。
我期待与任何人伸出援手合作。提前谢谢。
答案 0 :(得分:0)
只是想知道为什么要在示例#4的内部脚本中添加sandbox
属性?:
"<scr"+"ipt>window.top.document.getElementById('bryce_iframe').sandbox = 'allow-scripts';</scr"+"ipt>" +
沙箱属性应添加到父代码中:
<!-- Case #4 ~ Sandbox maybe not applied? -->
<script>
var i = document.createElement('iframe');
i.src = "about:blank";
i.id = "bryce_iframe";
i['sandbox'] = 'allow-scripts';
document.body.appendChild(i);
这将阻止父访问。
答案 1 :(得分:0)
我遇到了同样的问题。我也没有一个好的解决方案,但还有2个不能在Edge上工作的选项:
选项1:Blob网址
var blob = new Blob([html_string], {type: 'text/html'});
var url = URL.createObjectURL(blob);
var i = document.createElement('iframe');
i.src = url;
i.sandbox = "allow-scripts";
选项2:数据网址
var url = "data:text/html,<html_string>";
var i = document.createElement('iframe');
i.src = url;
i.sandbox = "allow-scripts";
答案 2 :(得分:0)
如果您查看HTML specification of the sandbox attribute,它会警告:
这些标志仅在导航iframe元素的嵌套浏览上下文时生效。
这意味着在加载iframe后,动态添加/删除/更新iframe的沙箱属性不会产生任何效果。
执行此操作的正确方法是在加载第三方JS的单独域中托管另一个HTML文件 。您可以在iframe的src
属性中引用该HTML文件,并且可以静态包含sandbox
属性,而不是尝试在JavaScript中动态添加它。确保包括allow-scripts
作为sandbox
属性的值,以便子页面能够加载JS。
您应将另一个HTML文件托管在单独的域中的原因是因为不支持sandbox
属性的浏览器。 here