为啥用户脚本中的窗口(和 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
时与从<script></script>
容器调用时不同。谁能解释一下为什么?
【问题讨论】:
【参考方案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_addStyle
、GM_xmlhttpRequest
、GM_log
和 GM_openInTab
。
但是,Tampermonkey 几乎完全支持 GM_
函数。
可能会导致副作用或与页面的 JS 冲突。
使用外部库会引入更多的冲突和时间问题。它远没有@require
简单。@require
还可以从本地副本运行外部 JS - 加快执行速度,几乎消除了对外部服务器的依赖。
页面可以查看、使用、更改或阻止脚本。
需要启用 JS。特别是 Firefox Greasemonkey 可以在 JS 被阻止的页面上运行。这对于臃肿、蹩脚和/或侵入性的页面来说可能是天赐之物。
【讨论】:
unsafeWindow
现在支持 Chrome
您写道“恶意网站管理员可能会跟踪 unsafeWindow 的使用回到脚本的上下文”。我不明白如果我的脚本没有安全漏洞怎么可能。以上是关于为啥用户脚本中的窗口(和 unsafeWindow)与 <script> 标记中的不同?的主要内容,如果未能解决你的问题,请参考以下文章
如何让我的用户脚本在隔离沙箱和 unsafeWindow 中执行代码?