是否可以通过用户脚本检测页面修改?

时间:2013-02-07 07:01:39

标签: javascript web-applications greasemonkey userscripts

如果您有网站,可以通过javascript用户脚本以某种方式查看访问者是否正在修改您的网站吗?

2 个答案:

答案 0 :(得分:4)

简而言之:EEEEEEK!不要这样做!相反,决定要保护的需要,并保护 。不惜一切代价避免轮询(定期检查)。特别是,避免定期对任何事情进行大量检查。


并非所有变更都可以跟踪。大多数变化都非常难以跟踪,因为有很多事情可能会发生变化。

可以检测到DOM的更改(新节点,已删除节点,已更改的属性)。另一个答案建议定期检查innerHTML,但最好使用mutation observers(由Firefox,Chrome支持)或较旧的突变事件(DOMSubtreeModified等)(支持因事件而异)代替。

除非通过手动比较每个方法和属性(eeeek),否则无法可靠地检测到标准方法的更改。这包括需要引用大量对象,包括Array.prototype.splice(当然还有ArrayArray.prototype),并运行脚本定期。但是,这不是用户通常所做的。

输入的状态是属性,而不是属性。这意味着文档HTML 将不会更改。如果脚本更改了状态,则change事件也不会触发。同样,唯一的解决方案是手动轮询每个输入(eeek)。

没有可靠的方法来检测是否已附加事件处理程序。对于初学者,您需要保护onX属性(第2段),检测对addEventListener(ek)的任何调用(不跳过第2段检查),检测对相应方法的任何调用由你的图书馆(jQuery.bind和其他几个人)。


一个对你有利的事情,可能是唯一一个:用户脚本在页面加载时运行(永远不会更早),所以你有足够的时间来准备你的防御。 / del> not even that plays in your favor(感谢Brock Adams注意和链接)

您可以通过将其替换为您自己的(ek)来检测已调用的标准方法。有许多方法需要以这种方式(eek),一些由浏览器,一些由您的框架。事实上,IE(甚至可以指示firefox,感谢@Brock)不会让你触摸DOM类的原型,为“eek”增加了另外一个“e”或两个“e”。一些方法只能通过方法调用(返回值,回调参数)获得的事实增加了另一个“e”或两个,总共“eeeek”。爬网整个window的想法将被安全异常和无法捕获的安全异常所挫败。也就是说,除非您不使用iFrame,否则您不在iFrame中。

即使您检测到每个方法调用,也可以通过写入innerHTML来更改DOM。 Firefox和Chrome支持Mutation Observers,因此您可以使用这些。

即使您检测到对预先存在的方法的每个方法调用并监听突变,大多数属性都不会反映出来,因此您还需要查看每个对象的所有属性。祈祷有人不会添加一个不可枚举的属性与你永远猜不到的密钥。顺便提一下,这也会捕获DOM突变。在ES6中,可以观察对象的属性集。我不确定你是否可以将一个setter附加到ES5中的现有对象属性(同时遵循ES3语法)。每个房产的投票都是eeeek。

当然,您应该允许您自己的脚本进行一些更改。工作流程是设置一个标志(不能从全球范围访问!)“我是合法的”,做你的工作,并清除标志 - 记住同样侧面所有的回调。然后方法观察者将检查标志是否已设置。属性监视器将更难以检测更改是否有效,但是可以从脚本通知每个合法更改(手动;再次确保用户脚本无法看到该通知流)。 Eeek。

我最初没有意识到完全不同的问题:用户脚本在页面加载时运行,但他们也可以创建一个iFrame。用户脚本将会:1)检测到你的脚本阻止程序,2)从轨道上查看页面(你无法阻止document.body.innerHTML =,这不是完全不可思议的(但仍然不太可能现在)最不是没有严重篡改document.body),3)插入一个iframe与原始URL(防止双重加载服务器端?)和4)有足够的时间在你的保护之前对空的iframe采取行动甚至装了。

另外,请参阅the duplicate found by Brock Adams,其中显示了我认为不应该做的其他几项检查。

答案 1 :(得分:0)

如果您自己没有更改内容的脚本,请将document.body.innerHTML和document.head.innerHTL与原来的内容进行比较。

当您在脚本中更改DOM时,您可以更新值以与其进行比较。使用setInterval定期进行比较。