如果您有一个网站,您能否以某种方式找出访问者是否正在使用 javascript 用户脚本修改您的网站?
2 回答
简而言之:EEEEEEK!不要这样做!相反,决定什么需要保护,然后保护那个。不惜一切代价避免轮询(定期检查)。特别是,避免对任何东西进行定期的重检查。
并非每个更改都可以跟踪。大多数变化都很难跟踪,因为有很多事情可以改变。
可以检测到对 DOM 的更改(新节点、删除的节点、更改的属性)。另一个答案建议innerHTML
定期检查,但最好使用突变观察者(Firefox、Chrome 支持)或较旧的突变事件(DOMSubtreeModified
等)(支持因事件而异)。
无法可靠地检测到标准方法的更改,除非手动比较每个方法和属性 (eeeek)。这包括需要引用大量对象,例如Array.prototype.splice
(当然还有),并定期运行Array
繁重的脚本。但是,这不是用户脚本通常所做的。Array.prototype
输入的状态是属性,而不是属性。这意味着文档 HTML不会改变。如果状态被脚本改变,change
事件也不会触发。同样,唯一的解决方案是手动轮询每个输入(eeek)。
没有可靠的方法来检测是否附加了事件处理程序。对于初学者,您需要保护onX
属性(第 2 段),检测对addEventListener
(ek) 的任何调用(不触发第 2 段检查),检测您的库(jQuery.bind
以及其他几个)对相应方法的任何调用。
对您有利的一件事,并且可能是唯一的一件事:用户脚本在页面加载时运行(永远不会更快),因此您有足够的时间来准备防御。 甚至没有对您有利(感谢 Brock Adams 的注意和链接)
您可以通过将其替换为您自己的 (ek) 来检测已调用的标准方法。您需要以这种方式(eek)检测许多方法,一些通过浏览器,一些通过您的框架。IE(甚至可以指示Firefox,感谢@Brock)不会让您触摸DOM类的原型这一事实在“eek”中添加了另一个“e”或两个。某些方法只能通过方法调用(返回值,回调参数)获得的事实增加了另一个“e”或两个,总共“eeeek”。爬过整个的想法window
将被安全异常和无法捕获的安全异常所挫败。也就是说,除非您不使用 iFrame 并且您不在 iFrame 中。
即使您检测到每个方法调用,也可以通过写入innerHTML
. Firefox 和 Chrome 支持 Mutation Observers,因此您可以使用它们。
即使您检测到对预先存在的方法的每个方法调用并监听突变,大多数属性都不会被两者反映,因此您还需要观察每个对象的所有属性。祈祷某人不要使用您永远猜不到的键添加不可枚举的属性。顺便说一句,这也会捕获 DOM 突变。在 ES6 中,可以观察对象的属性集。我不确定您是否可以将设置器附加到 ES5 中的现有对象属性(同时遵守 ES3 语法)。轮询每个属性是eeeek。
当然,您应该允许自己的脚本进行一些更改。工作流程是设置一个标志(不能从全局范围访问!)“我是合法的”,做你的工作,并清除标志 - 记住也要在你的所有回调的两侧。然后方法观察者将检查标志是否设置。属性看门狗将更难检测更改是否有效,但可以从脚本通知每个合法更改(手动;再次确保用户脚本看不到该通知流)。哎呀。
起初我没有意识到一个完全不同的问题:用户脚本在页面加载时运行,但它们也可以创建 iFrame。用户脚本会:1)检测您的脚本阻止程序,2)从轨道上删除页面(您无法阻止,至少在没有严重篡改的情况下无法阻止),3)插入一个具有原始 URL 的单个 iframe(防止双重加载服务器端?)和 4)有足够的时间在您的保护加载之前对该空 iframe 采取行动。document.body.innerHTML =
document.body
另外,请参阅Brock Adams 找到的副本,其中显示了我认为不应该进行的其他几项检查。
如果您自己没有脚本来更改您的内容,那么您可以将 document.body.innerHTML 和 document.head.innerHTL 与原来的内容进行比较。
当您在脚本中更改 DOM 时,您可以更新值以进行比较。使用 setInterval 定期比较。