【前端冷知识】如何禁止开发者操作网页上的DOM对象?

开发者福利!热门AI工具限时免费用 购周边即赠Coding Plan Lite,Claude Code、Cursor等20+工具畅享,效率翻倍! 阅读详情

通常情况下,在一个HTML页面上,我们总能够通过DOM API访问想要访问的HTML元素,进行操作。

如果基于某种原因,允许用户注入代码到网页上,但又要禁止用户对DOM对象进行操作,即只允许用户调用我们提供的API,不允许用户通过注入的JS来修改我们创建的UI组件甚至整个网页内容,那么我们要怎么做呢?

我们基本上无法通过JS来禁止用户通过注入的JS操作DOM,因为window对象、document对象这些对象以及它们的API是无法通过JS改写的:

window.document = 111;

console.log(window.document); // #document

如果我们用Object.getOwnPropertyDescriptor查看,会发现window.document实际上是一个getter,而且它的configurable是false。

Object.getOwnPropertyDescriptor(window, 'document');

// {get: ƒ, set: undefined, enumerable: true, configurable: false}

即使我们对允许用户合法注入的JS外面包裹函数作用域,我们还是无法彻底阻止用户访问document和window对象。

(function(window, document) {

  // user code

  console.log(this, window, document); // {}, null, null

  const win = (function () {

    return this;

  }());

  console.log(win); // Window

  // ---

}).call({}, null, null)

比如说上面的代码,我们在用户注入的代码前后增加包装代码,把window和document对象通过函数参数覆盖,我们还是能通过函数调用的this拿到window对象。

要防住这个漏洞,我们可以在包装的时候使用严格模式:

(function(window, document) {'use strict'

  // user code

  console.log(this, window, document); // {}, null, null

  const win = (function () {

    return this;

  }());

  console.log(win); // undefined

  // ---

}).call({}, null, null)

但是这个依然不解决问题:

(function(window, document) {'use strict'

  console.log(this, window, document); // {}, null, null

  const win = (function () {

    return this;

  }());

  console.log(win); // undefined

  setTimeout(function() {

    console.log(this); // Window

  });

}).call({}, null, null)

所以结论是包装代码无法让用户彻底无法访问window和document对象。

那么我们要怎么做既能合法让用户注入代码实现功能,又能够隔离window和document对象呢?

用worker做沙箱

第一种办法是只允许用户的代码跑在worker里。

我们知道worker的环境是和浏览器环境互相独立的线程,所以跑在worker里的代码是不能访问window和document对象的,这样就保证了安全性。

function execCodeInWorker(code) {

  const blob = new Blob([code]);

  const url = URL.createObjectURL(blob);


  const worker = new Worker(url);

  return worker;

}


const userCode = `

  console.log(typeof window, typeof document); // undefined undefined

`;


execCodeInWorker(userCode);

使用worker的问题是,当worker和浏览器环境通讯时,需要采用postMessage,如果有较多的交互操作,性能开销比较大,而且对写代码的开发者有使用成本。

使用Shadow DOM

如果我们只是不允许用户注入的JS修改UI,我们也可以将整个UI通过Shadow DOM渲染,并且将ShadowRoot的模式设置为closed封闭起来,这样的话,用户就无法拿到Shadow DOM的ShadowRoot对象,从而无法进行操作。

下面是一个简单的例子:

(function () {

  const root = document.body.attachShadow({mode: 'closed'});


  let list;


  function init() {

    root.innerHTML = `

      <h1>Todo List</h1>

      <ul></ul>

    `

    list = root.querySelector('ul');

  }


  function addTask(desc) {

    const task = document.createElement('li');

    task.textContent = desc;

    list.appendChild(task);

    return list.children.length - 1;

  }


  function removeTask(index) {

    const task = list.children[index];

    if(task) task.remove();

  }


  window.init = init;

  window.addTask = addTask;

  window.removeTask = removeTask;

}());


init();

addTask('task1');

我们通过document.body.attachShadow({mode: 'closed'});创建ShadowRoot,通过Shadow DOM API来创建UI,因为这个root对象我们没有暴露给用户,而且mode是closed,所以用户拿不到对象,无法通过DOM操作我们的UI,只能通过我们暴露给用户的addTask和removeTask来操作。

?注意,用户当然仍可以通过DOM API来往body中插入其他内容,但是,当一个元素创建了Shadow DOM,浏览器会优先渲染Shadow DOM,而忽略它的其他子元素,所以用户往body中插入任何内容都不会被渲染出来。唯一的例外是如果插入script标签,脚本会被执行,但是我们可以简单通过防止xss的代码过滤来阻止用户插入script标签。

这样,我们就通过Shadow DOM获得了一个相对安全的环境,对比worker的方式,可以避免postMessage的开销和拥有更简单的写法。当然Shadow DOM也有弊端,比如用户虽然不能改写当前body元素中渲染的内容了,但是可以彻底删掉body元素重新创建一个:

document.documentElement.removeChild(body);

const newBody = document.createElement('body');

document.documentElement.appendChild(newBody);

但是那样的话,原body中的所有内容也需要重建了。因此,使用Shadow DOM API至少大大增加了用户侵入的成本。

关于禁止开发者操作DOM对象的话题就谈到这里,还有什么可行的方法或者大家有什么想补充的,欢迎在issue中讨论。

关于奇舞周刊

《奇舞周刊》是360公司专业前端团队「奇舞团」运营的前端技术社区。关注公众号后,直接发送链接到后台即可给我们投稿。

640?wx_fmt=png

【爬与反爬】Javascript禁止前端调试页面 其实上面的各种方式并不能100%防止,毕竟javascript是客户端语言,就说别人把你的网站页面全部下载下来,然后把里面的js拦截代码一删,在本地一样嘎嘎跑,想咋调试就咋调试,所以说到底还是得从服务端想办法。 阅读详情

相关推荐

DOM 是什么?前端开发的网页操作核心机制

DOM(文档对象模型)是浏览器将 HTML 文本解析后生成的内存中树状结构,它不是 HTML 的副本,而是 Web 页面的运行时接口。其核心原理在于将静态标记转化为可编程的对象节点,支持 JavaScript 对页面结构、样式和事件的动态操控。DOM 提供了 getElementById、querySelector 等高效查询机制,并通过 document 对象统一暴露操作入口,构成前端工程化实践的技术基石。在现代架如 React 和 Vue 中,虚拟 DOM 与响应式更新均建立在对原生 DOM 行为的抽

weixin_34417200的博客 449

js阻止动态插入HTML(防止动态DOM插入广告)

主要使用用了js的MutationObserver的API接口提供了监视对DOM树来实现页面DOM的监听 MutationObserver文档: MutationObserver. 废话不多说上代码 ```javascript // 阻止后续DOM加载 class StopLoadingDOM { stop(DOM = 'body', stop_time = 60000) { //使用了E...

selfsummer的博客 1280

JavaScript的DOM知识点总结

JavaScript的DOM操作详解

ccj_cmp的博客 988

JS检测,禁用浏览器开发者工具之6大方法探讨

【第一种】debugger setInterval(function () { check() }, 1000); var check = function () { function doCheck(a) { if (("" + a / a)["length"] !== 1 || a % 20 === 0) { (function () { } .

橙-极纪元-JJYCheng 1万+

前端:页面安全问题,从前端角度使用js禁止用户修改页面代码

所周知,审查元素(F12或者右键检查)的情况下,大家都可以随机更改一部分页面的代码,注入恶意JS等等,这种情况避免也不难,虽然还能看到一部分H5源码,但是无法修改;所以我们可以通过一下三种方式解决问题:1、屏蔽F12 审查元素;2、屏蔽右键菜单来初步解决这些问题(也就是解决发现问题的人[偷笑]);3、在页面引用公共脚本使其自动进行JS调试(debug)。

weixin_44146294的博客 1802

浅谈shadow dom

什么是shadow dom?有什么特点?有什么用?为什么需要 shadow-dom?怎么创建shadow dom?如何修改shadow dom的样式? shadow-dom 的未来

TwInkle 2629

DOM

DOM对象简介 一、DOM对象 DOM,全称“Document Object Model(文档对象模型)”,它是由W3C组织定义的一个标准。 在前端开发时,我们往往需要在页面某个地方添加一个元素或者删除元素,这种添加元素、删除元素操作就是通过DOM来实现的。 DOM就是一个接口,我们可以通过DOM操作页面中各种元素,例如添加元素、删除元素、替换元素等。 DOM就是文档对象模型,文...

mmsx2017的博客 516

前端入门一之DOM获取元素DOM核心、事件高级、操作元素、事件基础、节点操作

文档对象模型简单理解:触发–响应机制如果有同一组元素,我们想要某一个元素实现某一种样式,需要用到循环的排他思想所有元素全部清空样式(干掉他人)给当前元素设置样式(留下我自己)注意顺序不能颠倒,首先干掉其他人,在设置自己。

羊小猪~~的博客 1877

解决网页pdf禁止打印的方案

网页禁止打印pdf解决办法

qq_43606857的博客 2万+

Codex 内置浏览器:前端开发者DOM 意图操作革命

DOM(文档对象模型)是 Web 前端的核心抽象,传统上需通过 JavaScript 手动遍历、查询与操作节点;而现代 AI 工具正从文本理解迈向真实 DOM 对象树的语义化交互。OpenAI Codex 内置浏览器功能标志着这一范式跃迁——它不再解析 HTML 字符串,而是构建轻量级、可响应的 DOM 快照对象树,并在安全沙箱中支持高亮、点击、输入等结构化操作。该能力直击前端开发高频痛点:动态渲染 SPA 元素定位难、表单自动化上下文丢失、跨架状态同步复杂。适用于 React/Vue 工程师、自动化测试

congsong2560的博客 474

你可能不知道的几个知识

inset 是一个复合属性,可一次性设置元素的 top、right、bottom 和 left 值。即便禁用了F12快捷键和右键菜单,用户仍可通过其他方式访问控制台。只需在浏览器控制台中输入这行代码,即可让整个页面变为可编辑状态。可以通过text-shadow属性来实现前端文本的马赛克效果。效果类似于CSS的user-select: none属性。直接使用DOM原生的hidden属性即可实现。

想好了再写! 421

前端开发者必备:突破网页防复制限制的实用技术指南

在Web开发与数据分析领域,DOM操作和网络请求分析是基础且核心的技术概念。DOM(文档对象模型)是网页内容的树状结构表示,开发者通过JavaScript可以动态修改其节点与样式,这是实现网页交互的底层原理。网络请求则是客户端与服务器通信的桥梁,通过分析XHR/Fetch请求,可以直接获取结构化数据。这些技术的工程价值在于,它们不仅能构建丰富的用户体验,也能在合法合规的前提下,解决实际工作中的信息获取瓶颈。例如,当遇到网页通过CSS属性(如user-select: none)或JavaScript事件监听来

weixin_34015336的博客 506

网页禁止复制粘贴修改

网页禁止复制和粘贴修改

GUEST_MTE的博客 2615

了解DOM和使用Javascript操作DOM

结合示例练习,了解DOMDOM操作

2501_90771362的博客 358

网页禁止用户复制粘贴的操作

本文探讨了通过禁用copy事件来防止网页内容被复制的技术实现,包括禁用输入输入、禁止特定文本复制、全局禁用复制功能以及禁用右键菜单等方法。但文章指出,仅靠前端限制并不能完全阻止内容复制,懂技术的用户可通过开发者工具绕过。建议结合禁用右键菜单、遮罩层和服务器端水印等多种手段,更有效地保护网页内容。文中提供了4种实现代码示例,展示了如何通过JavaScript事件监听来禁用复制操作

weixin_42400404的博客 482

WebAgent:基于DOM理解的端到端网页操作智能体

网页自动化是企业提效与用户体验升级的关键技术基础,其核心在于让AI真正理解网页结构与用户意图。传统方案依赖XPath硬编码、OCR识别或API对接,普遍存在脆弱性高、动态内容支持差、泛化能力弱等瓶颈。WebAgent创新性采用DOM树结构化输入+轻量视觉对齐+LLM动作规划三重架构,实现语言指令到浏览器原生交互的可靠闭环。它不依赖截图像素或静态HTML,而是实时感知JS渲染后的可访问语义(如aria-label、display状态),支撑比价、填表、抢票等真实任务,任务完成率达86%以上。本文深入解析其DO

weixin_34087307的博客 345

JS学习第3天——Web API之DOM获取元素操作元素、节点操作、insertAjacentHtml()方法、双击禁止选中文字、添加删除留言案例)

Web API之DOM获取元素操作元素、节点操作、insertAjacentHtml()方法、双击禁止选中文字、添加删除留言案例)

背心的博客 1320

web网页如何禁止别人移除水印

网页禁止用户移除水印是一个复杂的挑战,因为前端代码和页面内容本质上是由用户控制的。

qq_40576344的博客 808

javascript 禁止事件_前端——JavaScript

目录JS使用  文档内嵌  外部链接JavaScript 输入和输出语句  显示数据基础语法  变量  常量  数据类型  数据类型转换  运算符JS对象  数组 对象  字符串对象String  正则表达式对象 RegExp  Math 对象  日期对象流程控制  if结构  循环结构函数  调用函数DOM 文档对象模型  获取元素节点  添加/删除/替换 元素节点  改变HTML...

weixin_39785524的博客 883
上一篇: 花椒 Web 端多路音频流播放器研发
下一篇: 小程序底层实现原理及一些思考
奇舞周刊
博客等级 码龄7年 1898粉丝 568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值