如何防止水印被恶意删除或者隐藏?

继上篇 Vue3 实现网页背景水印功能 我们了解了常见的网页水印功能是如何实现的,懂原理的都知道水印是通过在网页中添加代码绘制 DOM 元素覆盖在原有的网页上而来的,一旦你打开浏览器中的元素审查,可以通过删除元素或者在元素的样式上操作属性值,就可以用来临时屏蔽水印。

为了防止作弊,我们可以利用接口 MutationObserver 对 DOM 元素进行监听。如果你对监听的元素进行样式属性的设置,或者对监听元素的子元素进行删除,都能通过 MutationObserver 的回调函数进行捕获,然后再针对你的修改操作进行复原。这样可以有效防止临时操作网页元素来隐藏水印。

MutationObserver 接口提供了监视对 DOM 树所做更改的能力。它被设计为旧的 Mutation Events 功能的替代品,该功能是 DOM3 Events 规范的一部分。

// 选择需要观察变动的节点
const targetNode = document.getElementById('some-id');// 观察器的配置(需要观察什么变动)
const config = { attributes: true, childList: true, subtree: true };// 当观察到变动时执行的回调函数
const callback = function(mutationsList, observer) {// Use traditional 'for loops' for IE 11for(let mutation of mutationsList) {if (mutation.type === 'childList') {console.log('A child node has been added or removed.');}else if (mutation.type === 'attributes') {console.log('The ' + mutation.attributeName + ' attribute was modified.');}}
};// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(callback);// 以上述配置开始观察目标节点
observer.observe(targetNode, config);// 之后,可停止观察
observer.disconnect();

了解如何使用之后,我们对上篇封装的增加水印功能的 hooks 进行优化,添加一个防删除的方法 antiDeletion,里面对水印元素和它的父级也就是 body进行了监听。

对父级元素进行监听,是为了捕获对它的删除操作,mutation 的类型为 childList,当删除水印元素的时候,我们通过回调参数 removedNodes 拿到删除元素的内容后再往它的父节点动态插入水印元素,相当于未删除成功。

a8c2c88b0439ca746ed517dffd2aa22e.png

然后还需要防止用户对水印元素进行样式属性的设置,比如 display: none;隐藏元素内容。这个时候我们添加对水印 DIV 层的监听,通过对 mutation 类型为attributes 的判断,然后强制给可能导致水印显示变化的样式进行复原操作。

const observers = [];
function antiDeletion() {const targetNode = unref(watermarkEl);const parentNode = unref(appendEl);const config = {childList: true,attributes: true,attributeOldValue: true,characterData: true,characterDataOldValue: true};observers[0] = new MutationObserver((mutationList, _observer) => {for (const mutation of mutationList) {const type = mutation.type;switch (type) {case "childList":console.log("childList", mutation);if (mutation.removedNodes.length > 0) {parentNode.appendChild(mutation.removedNodes[0]);}break;default:break;}}});observers[0].observe(parentNode, { childList: true });observers[1] = new MutationObserver((mutationList, _observer) => {for (const mutation of mutationList) {const type = mutation.type;switch (type) {case "attributes":console.log("attributes", mutation);if (mutation.attributeName === "style") {targetNode.style.display = "block";targetNode.style.zIndex = "100000";targetNode.style.top = "0px";targetNode.style.left = "0px";targetNode.style.position = "absolute";}if (mutation.attributeName === "class") {targetNode.style.setProperty("visibility","visible","important");}break;default:break;}}});observers[1].observe(targetNode, config);}

参考文档:https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver

- END -

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/354508.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jmc线程转储_如何分析线程转储– IBM VM

jmc线程转储本文是我们的线程转储分析系列的第4部分,它将为您提供什么是IBM VM的JVM线程转储以及您将找到的不同线程和数据点的概述。 您将看到和学习​​到,IBM VM Thread Dump格式是不同的,但是提供了更多现成的故障排除数据。 在这一点上&…

Java 8:使用交替接口公开的类型安全地图生成器

动态展示您的课程 当我是Java新手时,我记得当时想过应该有一种方法可以删除或隐藏我不想公开的类中的方法。 就像用private方法或类似方法覆盖public方法一样(哪种情况是不可能的,也不应该是不可能的)。 显然,今天&…

nodejs面试题

1、为什么用Nodejs,它有哪些缺点? 事件驱动,通过闭包很容易实现客户端的生命活期。不用担心多线程,锁,并行计算的问题V8引擎速度非常快对于游戏来说,写一遍游戏逻辑代码,前端后端通用当然Nodejs也有一些缺点…

sts-bundle的使用_使用WS-Trust / STS采样器扩展JMeter

sts-bundle的使用JMeter没有对WS-Security或WS-Trust的任何内置支持,这使我为JMeter开发了此STS采样器–可以在负载测试STS时使任何人的生活变得更好。 首先,您需要拥有Apache JMeter发行版。 我正在使用v2.7。 然后,您可以从此处下载sts.sam…

001_jdk配置

配置JAVA_HOME,CLASSPATH,PATH 其中JAVA_HOME必须的 JAVA_HOMEE:\java\jdk1.8.0_77 CLASSPATH(告诉java程序运行时,你的类或者类库在哪里) .; E:\java\jdk1.8.0_77\lib\dt.jar;E:\java\jdk1.8.0_77\lib\tools.jar;E:\java\jdk1.8.0_77\jre\lib\rt.jar 改成变量 .;%J…

python -- join()

python -- join()pythonjoinos月似当时,人似当时否?总 在 python 中,一共有两个 join 方法,一个是 str.join(),另一个是 os.path.join() ,这里只了解前一种 str.join(iterable) 官方文档 Return a string which is the…

Spark数据倾斜解决方案(转)

本文转发自技术世界,原文链接 http://www.jasongj.com/spark/skew/ Spark性能优化之道——解决Spark数据倾斜(Data Skew)的N种姿势 发表于 2017-02-28 | 更新于 2017-10-17 | 本文结合实例详细阐明了Spark数据倾斜的几种场景以及对应的解…

JavaParser入门:以编程方式分析Java代码

我最喜欢的事情之一是解析代码并对其执行自动操作。 因此,我开始为JavaParser做出贡献,并创建了两个相关项目: java-symbol-solver和Effectivejava 。 作为JavaParser的贡献者,我反复阅读了一些非常类似的问题,这些问…

GoldenGate Logdump基本使用

Logdump是GoldenGate复制软件中附带的一个工具软件,在OGG的目录下可以找到。这个工具主要用于分析OGG生成的队列文件,查找记录、统计队列文件中的数据等。 在OGG安装目录下执行logdump.exe or ./logdump即可进入命令行。 开始查找记录之前,先…

.bam.bai的意义_业务活动监视器(BAM)2.0带来的革命

.bam.bai的意义生产兼具精益和企业价值的中间件是一项艰巨的工作。 它要么不存在,要么需要创新的思维(很多),并且需要在实现中反复进行。 业务风险很大,但是如果您做对了,它就会使您领先于其他任何公司。 这…

数据结构和算法之排序五:选择排序

我们上一篇谈到了冒泡排序,其实我也说了,这两个排序方式何其相似,如果掌握了冒泡排序再来进行选择排序的理解我觉得完全没有太大的问题。那么什么叫做选择排序呢?我们可以理解为矮子里面挑高个,比如说呀有一个富翁来到…

Visual Studio Code使用问题

1、打开vscode黑屏 右击vscode快捷方式–>属性–>兼容性—>兼容模式打钩 重启vscode就可以了。 2、vscode终端没有显示路径,不能输入 显示如下图 则关闭VS Code ,右键单击VS Code 图标,选择属性->兼容性,取消勾选 已兼容模式运…

Java社区调查结果:74%的开发人员希望减少详细程度

一个新的JDK增强建议(JEP)在Java社区中风起云涌:JEP286。该建议建议在Java的未来版本中引入局部变量类型推断,以简化Java应用程序的编写。 在下面的文章中,我们将解释它的含义以及它将如何影响您的代码。 新帖&#…

coherence安装_Oracle Coherence:分布式数据管理

coherence安装本文介绍如何使用Oracle Coherence提供分布式(分区)数据管理。 在下面的示例应用程序中,创建了一个名为OTV的新集群,并且在该集群的两个成员之间分配了一个名为user-map的缓存对象。 二手技术: JDK 1.6.…

JavaFX技巧来节省内存! 属性和可观察物的阴影场

在 JavaFX的世界中, Properties API允许UI开发人员将值绑定到UI控件。 这种功能非常容易,但是当对象模型经常使用属性时,应用程序可能会很快耗尽内存。 我通常会编写两个单独的对象,例如pojo类和表示模型对象。 此技术通常在基于S…

如何在Hibernate Search 5.5.2 / Apache Lucene 5.4.x中处理停用词?

停用词,例如[“ a”,“ an”,“ and”,“ are”,“ as”,“ at”,“ be”,“ but”,“ by”,“ for”,“ if”,“在”,“成…

Java----前端验证之验证码额实现

验证码是常用的登录验证方式之一,最大的作用就是保证安全,验证码的生成在java中实现的方式有很多种,比如后台生成传输到前端页面,在前台直接生成进行验证,下面写一个最简单实现验证码验证登录的例子. 生成验证码: 验证码验证逻辑: From表单登录: 没错,就这么的简单.在scripts生…

使用Spring Boot隔离集成测试和模拟依赖项

集成测试可能很慢且不可靠,因为它们依赖于系统中过多的组件。 在某种程度上,这是不可避免的:这里的集成测试是为了验证系统的每个部分如何与其他内部或外部组件一起玩。 但是,我们可以通过仅分解所需的依赖关系而不是整个系统来改…

Ubuntu 16.04下使用Wine安装Xshell 4和Xftp 4

说明: 1、使用的Wine版本是深度出品(Deepin),已经精简了很多没用的配置,使启动能非常快,占用资源小。 2、由于Xshell 5的C库无法在这个Wine版本运行,即使升级官方原版的2版本也无法解决&#xf…

电脑缺失MSVCP110.dll文件

安装某软件显示如下错误。 错误: 原因:电脑缺少MSVCP110.dll系统文件。C:\Windows\System32目录下没有此文件。 解决: 下载vcredist_x64直接双击安装,安装完成后就可以继续安装之前安装不了的软件了。。 这里是我下载的&#…