背景
Greasemonkey 不是已经注入我的扩展 JavaScript 了吗?有人可以为我澄清一下吗。
Greasemonkey 在沙箱中执行您的脚本,这是一个受限环境,无法直接访问页面中的 JavaScript。早期版本的 Greasemonkey 将脚本直接注入页面,但这会引入严重的安全漏洞。在旧模型中,脚本以浏览器 chrome 的提升权限运行,这允许远程页面使用一些巧妙的 JavaScript访问 Greasemonkey 的内置函数。这很糟糕:
Greasemonkey 脚本包含它们自己的 GM_xmlhttprequest 对象,与普通的 xmlttprequest 对象不同,该对象可以访问计算机的任何本地文件或向任意站点发出任意请求,而无需考虑通常适用于 xmlhttprequest 的相同来源策略。(来源)
今天,当您从 Greasemonkey 脚本访问该window
对象时,您得到的是一个间接引用实际属性的包装器对象window
。这个包装对象可以安全地修改,但有重要的限制。对实际窗口对象的访问由unsafeWindow
(的简写window.wrappedJSObject
)提供。使用unsafeWindow
重新打开 Greasemonkey 的所有原始安全问题,并且在 Chrome 中不可用。应尽可能避免。
好消息:至少有两种方法可以安全地使用 Greasemonkey 的新安全模型。
脚本注入
现在 Greasemonkey 脚本可以安全地访问 DOM,将<script>
标签注入到<head>
目标文档中就很简单了。创建一个这样的函数:
function exec(fn) {
var script = document.createElement('script');
script.setAttribute("type", "application/javascript");
script.textContent = '(' + fn + ')();';
document.body.appendChild(script); // run the script
document.body.removeChild(script); // clean up
}
使用简单:
exec(function() {
return Grooveshark.playNextSong();
});
定位黑客
在某些情况下,脚本注入可能有点过头了,尤其是当您只需要修改页面中变量的值或执行单个函数时。Location Hack利用URL 来访问文档内容中的javascript:
代码。这很像在 Greasemonkey 脚本中运行书签。
location.assign("javascript:Grooveshark.playNextSong();void(0)");
奖金脚本
这是一个完整的 Greasemonkey 脚本,演示了上面的示例。您可以在此页面上运行它。
// ==UserScript==
// @name Content Function Test
// @namespace lwburk
// @include http://stackoverflow.com/questions/5006460/userscripts-greasemonkey-calling-a-websites-javascript-functions
// ==/UserScript==
function exec(fn) {
var script = document.createElement('script');
script.setAttribute("type", "application/javascript");
script.textContent = '(' + fn + ')();';
document.body.appendChild(script); // run the script
document.body.removeChild(script); // clean up
}
window.addEventListener("load", function() {
// script injection
exec(function() {
// alerts true if you're registered with Stack Overflow
alert('registered? ' + isRegistered);
});
// location hack
location.assign("javascript:alert('registered? ' + isRegistered);void(0)");
}, false);