Dav*_*lfe 3 html javascript greasemonkey same-origin-policy
在下面的 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>
Run Code Online (Sandbox Code Playgroud)
我打算inner_frame_2使用 Userscript获取和修改嵌套 iframe(例如)中的值,因此应该可以绕过同源策略。但是示例GM_xmlhttpRequest似乎依赖于 GET/POST 请求,而我只想处理这些 iframe 中已经加载的页面数据。
我是误解了GM_xmlhttpRequest,还是我应该在这里采取另一种方法?
我认为您可以做到的唯一方法是使用该window.postMessage()方法将带有数据的消息从 iframe 发送到顶部窗口。要捕获 Greasemonkey 脚本中的每个 iframe,请参阅Brock Adams在将Greasemonkey 用户脚本应用到 iframe上的回答?; 你必须@match像这样使用 GM指令:
// @match http://subdomain1.example.com/*
Run Code Online (Sandbox Code Playgroud)
或者
// @match *.example.com/*
Run Code Online (Sandbox Code Playgroud)
然后您可以检查当前窗口是否是顶部窗口,和/或检查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
}
})();
Run Code Online (Sandbox Code Playgroud)
我们需要将一个事件挂接"message"到顶部窗口,该窗口将处理从 iframe 接收到的带有数据的每条消息:
window.addEventListener("message", function(event) {
// do something with the event.data
}, false);
Run Code Online (Sandbox Code Playgroud)
我们可以通过使用来识别 iframe document.domain;对 iframe 元素进行任何我们需要的操作;检索我们想要的所有数据并将消息发送到顶部窗口:
window.top.postMessage({
// data object we send to the top window
}, "*");
Run Code Online (Sandbox Code Playgroud)
我创建了一个演示来尝试这个,它工作得很好。我的顶部窗口 URL 是http://zikro.gr/dbg/gm/iframes/main.php,子域就像http://subdomain1.zikro.gr/. 顶部窗口 HTML 与我的 iframe url 和 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
}, "*");
}
})();
Run Code Online (Sandbox Code Playgroud)
对于那些没有安装 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>
Run Code Online (Sandbox Code Playgroud)