在以下HTML模型中,嵌套的iframe源自不同的子域。这导致消息,例如错误:权限被拒绝访问属性“文档”
<html>
<head>
<title></title>
</head>
<body>
<div>
<iframe id="outer_iframe_1" src="https://subdomain1.example.com"></iframe>
</div>
<div>
<iframe id="outer_iframe_2" src="https://subdomain2.example.com">
<div>
<iframe id="inner_iframe_2" src="https://subdomain4.example.com"></iframe>
</div>
</iframe>
</div>
<div>
<iframe id="outer_iframe_3" src="https://subdomain3.example.com"></iframe>
</div>
</body>
</html>
我打算使用Userscript获取和修改嵌套iframe中的值(例如。inner_frame_2
),因此绕过同源策略应该是可能的。但是GM_xmlhttpRequest
的示例似乎依赖于GET / POST请求,而我只想处理这些iframe中已经加载的页面数据。
我误解了GM_xmlhttpRequest
,还是我应该采取另一种方法?
答案 0 :(得分:2)
我认为唯一可行的方法是使用window.postMessage()
方法将包含iframe数据的邮件发送到顶部窗口。要在Greasemonkey脚本中捕获每个iframe,请参阅Brock Adams answer上的Apply a Greasemonkey userscript to an iframe?;你必须使用这样的GM @match
指令:
// @match http://subdomain1.example.com/*
或
// @match *.example.com/*
然后你可以检查当前窗口是否是顶部窗口,和/或检查document.domain
以识别iframe:
// ==UserScript==
// @name New Userscript
// @match http://main-domain.something
// @match *.example.com/*
// ==/UserScript==
(function() {
'use strict';
if (window.top === window.self) {
// Here we are at the top window and we setup our message event listener
}
else {
// Here we get inside the iframes.
// We can address and check each iframe url with document.domain
}
})();
我们需要将"message"
的事件挂钩到顶部窗口,该窗口将处理从iframe接收的每条消息及其数据:
window.addEventListener("message", function(event) {
// do something with the event.data
}, false);
我们可以使用document.domain
识别iframe;对iframe元素进行任何操作;检索我们想要的所有数据并将消息发送到顶部窗口:
window.top.postMessage({
// data object we send to the top window
}, "*");
我创建了一个试用这个的演示,它运行得很好。我的首页窗口网址为http://zikro.gr/dbg/gm/iframes/main.php
,子域名为http://subdomain1.zikro.gr/
。顶部窗口HTML与我的iframe网址和GM脚本相同:
// ==UserScript==
// @name New Userscript
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match http://zikro.gr/dbg/gm/iframes/main.php
// @match *.zikro.gr/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
if (window.top === window.self) {
// Here we are at the top window and we setup our message event listener
document.body.style.backgroundColor = "#f00"; // Just a UI change to identify the top window
window.addEventListener("message", function(event) {
window.console.log("This is data from '" + event.data.title +
"'; with message '" + event.data.message +
"'; with data '" + event.data.data +"'" +
"'; from domain '" + event.data.domain + "'");
}, false);
}
else {
// Here we get inside the iframes.
// We can address and check each iframe url with document.domain
document.body.style.backgroundColor = "#0f0"; // Just a UI change to identify the iframe window
// We change something inside the iframe
var dataDiv = document.getElementsByTagName('div')[0];
dataDiv.innerHTML += " with a change!";
// And we post a message to the top window with all the data we want inside an object
window.top.postMessage({
title: document.title,
domain: document.domain,
message: "Hello from, iframe - " + document.title,
data: dataDiv.innerText
}, "*");
}
})();
为那些没有安装Greasemonkey / Tampermoney的人进行屏幕截图测试:
PS:在iframe代码中直接添加元素是无效的:
<iframe id="outer_iframe_2" src="https://subdomain2.example.com">
<div>
<iframe id="inner_iframe_2" src="https://subdomain4.example.com"></iframe>
</div>
</iframe>
答案 1 :(得分:0)
这不是您问题的直接答案,但这适用于那些希望使用javascript操作网页进行数据处理的人。
PhantomJS等软件专为&#34;浏览器自动化而设计。并允许完全删除交叉原始政策。
page.open("http://fiddle.jshell.net/9aQv5/show/", function(status) { // Load a webpage
page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js", function() { // Add support jor jQuery
page.evaluate(function() { // Run custom script
console.log($("body").find("iframe").attr("src"));
console.log($("body").find("iframe").contents().find("iframe").attr("src"));
console.log($("body").find("iframe").contents().find("iframe").contents().find("#about-puppy-linux").html());
});
phantom.exit(0);
});
});
在您的脚本中,您可以使用
//fiddle.jshell.net/9aQv5/show/light/
http://www.puppylinux.com/
About Puppy Linux
您将获得以下输出:
{{1}}