用于绕过同源策略以访问嵌套 iframe 的用户脚本
Userscript to bypass same-origin policy for accessing nested iframes
在下面的 HTML 模型中,嵌套的 iframe 来自不同的子域。这会导致诸如 error: Permission denied to access 属性 "document"
之类的消息
<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>
我打算使用用户脚本获取和修改嵌套 iframe(例如 inner_frame_2
)中的值,因此应该可以绕过同源策略。但是 GM_xmlhttpRequest
的示例似乎依赖于 GET/POST 请求,而我只想处理这些 iframe 中已经加载的页面数据。
我是不是误解了GM_xmlhttpRequest
,还是我应该采取另一种方法?
我认为你能做到的唯一方法是使用这样的 window.postMessage()
method to send messages with data from iframes to the top window. To catch each iframe inside Greasemonkey script see on ; you'll have to use the GM @match
指令:
// @match http://subdomain1.example.com/*
或
// @match *.example.com/*
然后可以查看当前window是否是置顶window,and/or查看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"
的事件挂接到顶部 window 以处理从 iframe 接收到的每条消息和数据:
window.addEventListener("message", function(event) {
// do something with the event.data
}, false);
并且我们可以使用 document.domain
来识别 iframe;对 iframe 元素进行我们需要的任何操作;检索我们想要的所有数据并将消息发送到顶部 window:
window.top.postMessage({
// data object we send to the top window
}, "*");
我创建了一个演示来尝试这个,它工作得很好。我的顶级 window URL 是 http://zikro.gr/dbg/gm/iframes/main.php
,子域类似于 http://subdomain1.zikro.gr/
。顶部 window 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>
这不是您问题的直接答案,但这是为那些想要使用 javascript 操纵网页以进行数据处理的人准备的。
PhantomJS 等软件专为 "browser automation" 设计,允许完全删除跨源策略。
phantomjs.exe --web-security=no script.js
在您的脚本中,您可以使用
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
在下面的 HTML 模型中,嵌套的 iframe 来自不同的子域。这会导致诸如 error: Permission denied to access 属性 "document"
之类的消息<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>
我打算使用用户脚本获取和修改嵌套 iframe(例如 inner_frame_2
)中的值,因此应该可以绕过同源策略。但是 GM_xmlhttpRequest
的示例似乎依赖于 GET/POST 请求,而我只想处理这些 iframe 中已经加载的页面数据。
我是不是误解了GM_xmlhttpRequest
,还是我应该采取另一种方法?
我认为你能做到的唯一方法是使用这样的 window.postMessage()
method to send messages with data from iframes to the top window. To catch each iframe inside Greasemonkey script see @match
指令:
// @match http://subdomain1.example.com/*
或
// @match *.example.com/*
然后可以查看当前window是否是置顶window,and/or查看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"
的事件挂接到顶部 window 以处理从 iframe 接收到的每条消息和数据:
window.addEventListener("message", function(event) {
// do something with the event.data
}, false);
并且我们可以使用 document.domain
来识别 iframe;对 iframe 元素进行我们需要的任何操作;检索我们想要的所有数据并将消息发送到顶部 window:
window.top.postMessage({
// data object we send to the top window
}, "*");
我创建了一个演示来尝试这个,它工作得很好。我的顶级 window URL 是 http://zikro.gr/dbg/gm/iframes/main.php
,子域类似于 http://subdomain1.zikro.gr/
。顶部 window 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>
这不是您问题的直接答案,但这是为那些想要使用 javascript 操纵网页以进行数据处理的人准备的。
PhantomJS 等软件专为 "browser automation" 设计,允许完全删除跨源策略。
phantomjs.exe --web-security=no script.js
在您的脚本中,您可以使用
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