为啥用户脚本中的窗口(和 unsafeWindow)与 <script> 标记中的不同?

Posted

技术标签:

【中文标题】为啥用户脚本中的窗口(和 unsafeWindow)与 <script> 标记中的不同?【英文标题】:Why is window (and unsafeWindow) not the same from a userscript as from a <script> tag?为什么用户脚本中的窗口(和 unsafeWindow)与 <script> 标记中的不同? 【发布时间】:2012-06-05 04:26:03 【问题描述】:

我在开发这个small userscript 时遇到了一个问题。当我想用我的脚本阻止正在运行的网站上的每个 XMLHttpRequest 时,什么都没有发生(至少在 Chrome 中):

function main() 
  // Override XHR.open with a custom function
  window.XMLHttpRequest.prototype.open = function() 
    // Nothing... so it's supposed to block every xhr.open() call
  

main();

window 替换为unsafeWindow 时也是如此。

但是,当我使用这个小技巧时,一切都像魅力一样:

// No more call to main(), and:
var script = document.createElement("script");
script.textContent = "(" + main.toString() + ")();";
document.body.appendChild(script);

xhr.open 的每次调用都被我的自定义函数替换,不再是 AJAX。

所以我猜window 元素在从脚本内部调用main 时与从&lt;script&gt;&lt;/script&gt; 容器调用时不同。谁能解释一下为什么?

【问题讨论】:

【参考方案1】:

见"Are Chrome user-scripts separated from the global namespace like Greasemonkey scripts?"。 Chrome 用户脚本/内容脚本和 Greasemonkey 脚本都与页面的 javascript 隔离。这样做是为了防止您被黑客入侵,但也可以减少冲突和意外的副作用。

但是,每个浏览器的方法都不同...

火狐:

    在an XPCNativeWrapper sandbox 中运行脚本,除非@grant none 生效(自GM 1.0 起)。 默认情况下将脚本包装在匿名函数中。 提供unsafeWindow 访问目标页面的javascript。但请注意,敌对网站管理员可能跟踪unsafeWindow 的使用回到脚本的上下文,从而获得提升的权限来攻击你。

铬:

    在an "isolated world" 中运行脚本。 将脚本包装在匿名函数中。 严格阻止脚本对页面 JS 的任何访问,反之亦然。 Chrome 的最新版本现在提供了一个名为 unsafeWindow 的对象,用于非常有限的兼容性,但该对象不提供对目标页面 JS 的任何访问。它与脚本范围内的window 相同(而不是页面范围内的window)。

也就是说,如果正确实施,使用 unsafeWindow 的脚本版本应该可以在 Firefox 上/在 Firefox 中运行。它可能在 Chrome 上使用 the Tampermonkey extension 工作,但我现在不打算仔细检查。

当您执行该“技巧” (var script = document.createElement("script"); ...) 时,您就是在将代码注入 到目标页面中。这绕过了沙箱,并且是普通 Chrome 用户脚本上脚本与页面 JS 交互的唯一方法。

注射优势:

    非 Tampermonkey 用户脚本访问目标页面提供的对象或功能的唯一途径。 在 Chrome、Firefox、Opera 等之间几乎总是完全兼容(IE 一如既往地不同。) 通常更容易调试整个脚本;开发者工具正常工作。

注射缺点:

    脚本,至少是注入的部分,不能使用GM_函数提供的增强权限(尤其是跨域)——尤其是GM_xmlhttpRequest()。 请注意,目前Chrome 仅完全原生地支持 GM_addStyleGM_xmlhttpRequestGM_logGM_openInTab。 但是,Tampermonkey 几乎完全支持 GM_ 函数。

    可能会导致副作用或与页面的 JS 冲突。

    使用外部库会引入更多的冲突和时间问题。它远没有@require 简单。@require 还可以从本地副本运行外部 JS - 加快执行速度,几乎消除了对外部服务器的依赖。

    页面可以查看、使用、更改或阻止脚本。

    需要启用 JS。特别是 Firefox Greasemonkey 可以在 JS 被阻止的页面上运行。这对于臃肿、蹩脚和/或侵入性的页面来说可能是天赐之物。

【讨论】:

unsafeWindow 现在支持 Chrome 您写道“恶意网站管理员可能会跟踪 unsafeWindow 的使用回到脚本的上下文”。我不明白如果我的脚本没有安全漏洞怎么可能。

以上是关于为啥用户脚本中的窗口(和 unsafeWindow)与 <script> 标记中的不同?的主要内容,如果未能解决你的问题,请参考以下文章

如何让我的用户脚本在隔离沙箱和 unsafeWindow 中执行代码?

为啥我的脚本无法检查数据库中的相似用户名? [复制]

如何在 Google Chrome 的 Greasemonkey 脚本中使用 jQuery?

为啥python用inqut输入后窗口的类执行不了

loadrunner11为啥不能录制google浏览器

为啥我的 LDAP 重定向脚本对一个用户失败?