我在我的HTML页面中加载一个<iframe>,并试图使用JavaScript访问其中的元素,但当我尝试执行我的代码时,我得到以下错误:
阻止原点为“http://www.example.com”的帧访问跨原点帧。
如何访问框架中的元素?
我正在使用这段代码进行测试,但徒劳:
$(document).ready(function() {
var iframeWindow = document.getElementById("my-iframe-id").contentWindow;
iframeWindow.addEventListener("load", function() {
var doc = iframe.contentDocument || iframe.contentWindow.document;
var target = doc.getElementById("my-target-id");
target.innerHTML = "Found it!";
});
});
如果你可以控制iframe的内容——也就是说,如果它只是在一个跨起源的设置中加载,比如在Amazon Mechanical Turk上——你可以用<body onload='my_func(my_arg)'>属性来规避这个问题。
例如,对于内部html,使用this html参数(yes -这是定义的,它引用内部主体元素的父窗口):
<身体onload = ' changeForm(这)>
在内部html:
function changeForm(window) {
console.log('inner window loaded: do whatever you want with the inner html');
window.document.getElementById('mturk_form').style.display = 'none';
</script>
如果你可以控制iframe的内容——也就是说,如果它只是在一个跨起源的设置中加载,比如在Amazon Mechanical Turk上——你可以用<body onload='my_func(my_arg)'>属性来规避这个问题。
例如,对于内部html,使用this html参数(yes -这是定义的,它引用内部主体元素的父窗口):
<身体onload = ' changeForm(这)>
在内部html:
function changeForm(window) {
console.log('inner window loaded: do whatever you want with the inner html');
window.document.getElementById('mturk_form').style.display = 'none';
</script>
检查域的web服务器的X-Frame-Options的http://www.example.com配置
这是一个安全功能,旨在防止点击劫持攻击,
点击劫持是如何工作的?
邪恶页面看起来和受害者页面一模一样。
然后它诱使用户输入用户名和密码。
从技术上讲,邪恶有一个iframe的源受害者页面。
<html>
<iframe src='victim-domain.example'/>
<input id="username" type="text" style="display: none;"/>
<input id="password" type="text" style="display: none;"/>
<script>
//some JS code that click jacking the user username and input from inside the iframe...
<script/>
<html>
安全特性是如何工作的
如果你想阻止web服务器请求在iframe中呈现,添加x-frame-选项
X-Frame-Options否认
选项是:
只允许我自己的域渲染我的HTML在一个iframe。
DENY:不允许我的HTML在任何iframe内渲染
allow - from https://example.com/:允许特定的域在iframe内渲染我的HTML
这是IIS配置示例:
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="SAMEORIGIN" />
</customHeaders>
</httpProtocol>
问题的解决方案
如果web服务器激活了安全特性,可能会导致客户端SecurityError错误。
实际上,在特定的情况下,有一个变通办法。
如果在同一个域上运行两个进程,但端口不同,那么两个Windows可以不受限制地交互。(即localhost:3000 & localhost:2000)。为了实现这一点,每个窗口都需要将它们的域更改为共享源:
document.domain = 'localhost'
这也适用于您正在使用同一二级域上的不同子域的场景,即您在john.site.example上试图访问peter.site.example或只是site.example
document.domain = 'site.example'
通过显式设置document.domain;浏览器将忽略主机名的差异,Windows可以被视为来自“同源”。现在,在父窗口中,你可以进入iframe:
对我来说,我想实现一个双向握手,这意味着:
父窗口的加载速度比iframe快
iframe应该在准备好后立即与父窗口对话
-父节点已经准备好接收iframe消息并重播
此代码用于在iframe中使用[CSS自定义属性]设置白色标签
代码:
iframe
$(function() {
window.onload = function() {
// create listener
function receiveMessage(e) {
document.documentElement.style.setProperty('--header_bg', e.data.wl.header_bg);
document.documentElement.style.setProperty('--header_text', e.data.wl.header_text);
document.documentElement.style.setProperty('--button_bg', e.data.wl.button_bg);
//alert(e.data.data.header_bg);
}
window.addEventListener('message', receiveMessage);
// call parent
parent.postMessage("GetWhiteLabel","*");
}
});
父
$(function() {
// create listener
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
eventer(messageEvent, function (e) {
// replay to child (iframe)
document.getElementById('wrapper-iframe').contentWindow.postMessage(
{
event_id: 'white_label_message',
wl: {
header_bg: $('#Header').css('background-color'),
header_text: $('#Header .HoverMenu a').css('color'),
button_bg: $('#Header .HoverMenu a').css('background-color')
}
},
'*'
);
}, false);
});
当然,您可以限制起源和文本,这很容易与代码一起工作
我发现下面这个例子很有帮助:
[使用postMessage的跨域消息传递]