轻松检测用户何时更改DOM

4

如何轻松检测用户对DOM的操作?

当用户在任何现代浏览器中使用控制台时,他/她可以以开发者不想要的方式操纵DOM。

我有一个非常依赖DOM处于特定状态的Web应用程序,如果用户通过控制台对DOM进行任何操作,我希望得到通知。

答案:

  1. 不需要跨浏览器适用
  2. 不需要完美。我完全理解大多数(如果不是全部)方法都可以被规避,但我想要一个好的通用解决方案。
  3. 不能过于复杂。 我对注册一个事件处理程序来检查代码执行DOM操作时设置的某些标志的所有DOM事件不感兴趣

编辑:

到目前为止,我收到的答案中似乎存在一些混淆。如上所述,在#2中指出,我了解大多数(如果不是全部)方法都可以被规避。

此外,这是一个内部工具,因此受VPN的保护。 此外,还进行服务器端检查。 但是,出于某些我无法详细说明的原因,我希望知道用户(数量很少)何时操作了DOM。

明确一下,这不是出于安全原因。 我在这里没有试图阻止恶意用户。 将其视为出于好奇心。


1
用户操作DOM有什么问题吗?您的应用程序不应该在客户端执行任何敏感操作(例如处理身份验证)。如果应用程序“依赖于DOM处于某些状态”,而用户更改了DOM,则当应用程序停止工作时,他们不能抱怨。 - Xenon
"DOM变动事件"可能是关键词:https://developer.mozilla.org/zh-CN/docs/DOM/Mutation_events - Samuli Hakoniemi
https://dev59.com/w3E85IYBdhLWcg3wUBkZ - Sidharth Mudgal
2
你不能相信客户端,服务器需要验证所有提交给它的内容。用户甚至不需要使用你的网页就可以通过命令行提交请求。 :) - epascarello
6个回答

6

不要这样做。编写你的网站以不信任用户输入,并且不要关心用户做什么。如果提交无效输入,则拒绝它。这样每个人都会很高兴。

很容易认为你拥有用户的浏览器。但你并没有。它为你服务,但只在用户的意愿下。

如果你真的必须知道DOM何时被修改,而这似乎是一个非常脆弱的设计,那就计算校验和。在网站的批准功能的每个合法步骤之后,遍历你关心的DOM元素并记录它们的位置、值或其他你关心的内容。在间隔时间、验证时间或下一个UI交互中进行比较。这是唯一全面的、跨浏览器(包括旧浏览器)检测DOM更改的方法。现代浏览器提供了DOM突变事件(请参见Tim Down的答案以获取更多详细信息),但支持有限,而且显然将被另一个新东西取代。

最终,任何你所做的事情都不能阻止有决心打败你方案的人。如果有什么区别,用户可以使用Firebug复制浏览器的POST请求,调整它,并编写一个小程序来提交他自己的恶意POST请求。比起使你的网页看似防弹(因为它不会),更重要的是保护你的服务器免受恶意输入的攻击。


5

DOM变异事件在所有主流浏览器的当前版本中都可以使用,而且可以实现你想要的功能。以下内容将涵盖整个文档中常见的DOM修改:

function handleDomChange(evt) {
    console.log("DOM changed via event of type " + evt.type);
}

document.addEventListener("DOMNodeInserted", handleDomChange, false);
document.addEventListener("DOMNodeRemoved", handleDomChange, false);
document.addEventListener("DOMCharacterDataModified", handleDomChange, false);

DOM变异事件最终将被最近Mozilla和WebKit浏览器中实现的变异观察器所取代。


这很有趣,但是属性变化比如CSS更改呢? - ErikE
@ErikE:据我所知,没有CSS变异事件,快速搜索也没有找到太多信息。您可以使用DOMAttrModified来监视对style属性的更改(尽管我不确定特定事件的浏览器支持情况),但否则您可能需要通过document.stylesheets轮询现有的样式规则。 - Tim Down

2
依赖脚本来防止或对抗恶意修改DOM并不是正确的方法。你到底在做什么,需要依赖于DOM不能被触碰?这似乎本身就是一个巨大的警示。

1
你好,欢迎来到Stack Overflow。通常需要澄清的请求应该作为评论而不是答案发布。然而,我同意你的观点,这并不是正确的方法,所以我建议你编辑你的答案,删除问题并集中讨论为什么这是错误的,以及有哪些替代方案。这将确保你的答案符合[faq]中的指南,并成为一个完整的答案。祝你好运! :) - jamesmortensen
“那本身就是一个巨大的警示标志” - 绝对明智。如果您不希望用户拥有更改DOM的权限或能力,那么您的应用程序确实不应该在浏览器中运行。 - netpoetica

1
这是一个非常有趣的问题,我认为DOM变异事件可能是最好的解决方案。一开始我想做的一件事是运行一个定时函数,根据数据属性或ID检查DOM中特定的模块。如果我完全通过JS构建我的页面,我会为每个模块(像DOM元素一样)创建一个构建配置对象。
<div id='weather-widget' data-module-type='widget'>
    <h1 data-module-name='weather'>Weather</h1>
    <!-- etc etc -->
</div>

无论如何,我的配置对象将包含所有这些内容,例如模块类型、模块名称等等:

//Widget configuration object
var weatherWidgetConfig = {
    type: 'widget',
    name: 'weather'
}

我会检查DOM元素及其所有子元素,确保data-属性仍与配置对象匹配,它们存在且未被更改。如果有更改,我将使用正确的配置再次调用module.destroy()和module.build()。

1

我收到了很多回答,其中回答者提供了有关如何构建Web应用程序的建议。虽然这对某些读者可能有用,但这并没有回答问题。然而,一些人尝试着回答。我看到的最完整的答案是由@Keith给出的。唯一的问题是它未能通过“易用性”测试。

似乎正确的答案,正如一些人所说,是NO-无法轻松地检测用户的DOM操作。


0

最近我发现了一种名为“Selector Listener”的技术,它依赖于CSS来检测DOM更改。它无法在IE 9-中工作。将其应用于整个DOM听起来不是一个好主意,而是更适合使用特定的选择器。

更多细节可以在这篇博客文章中找到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接