当前位置: 首页 > Web前端 > HTML

实现页面水印与MutationObserver有什么关系?

时间:2023-03-28 11:35:25 HTML

序大家好,我是林三鑫。用最通俗易懂的语言解释最难的知识点是我的座右铭,难免??会遇到一个问题——给页面加水印其实并不难,但是有一些需要注意的地方,所以对于看似简单的功能,我们要尽量做到:1.严谨性2.安全实现水印实现水印并不难,只需要使用自定义指令+canvas+background-image,实现起来也很方便:importtype{Directive,App}from'vue'interfaceValue{font?:stringtextColor?:stringtext?:string}constwaterMarkId='waterMark'constcanvasId='can'constdrawWatermark=(el,value:Value)=>{const{font='16pxMicrosoftJhengHei',textColor='rgba(180,180,180,0.3)',text='三心菜鸟',}=value//创建一个画布标签constcanvas=document.getElementById(canvasId)asHTMLCanvasElement//如果已经存在就不要创建constcan=canvas||document.createElement('canvas')can.id=canvasIdel.appendChild(can)//设置宽高can.width=400can.height=200//不可见can.style.display='none'constctx=can.getContext('2d')!//设置画布的样式ctx.rotate((-20*Math.PI)/180)ctx.font=fontctx.fillStyle=textColorctx.textAlign='left'ctx.textBaseline='middle'ctx.fillText(text,can.width/3,can.height/2)//水印容器constwaterMaskDiv=document.createElement('div')waterMaskDiv.id=waterMarkId//设置容器的属性样式//将新生成的canvas内容转换为图片,赋给容器的background-image样式conststyleStr=`width:100%;高度:100%;位置:固定;z-索引:-1;顶部:0;左:0;指针事件:无;background-image:url(${can.toDataURL('image/png')})`waterMaskDiv.setAttribute('style',styleStr)//将水印容器放在目标元素下el.appendChild(waterMaskDiv)returnstyleStr}constwatermarkDirective:Directive={mounted(el,{value}){//接收styleStr,后面可以用来比较el.waterMarkStylestr=drawWatermark(el,value)}}使用时直接使用v-watermark:得到的效果如下:恶意修改水印功能我们已经完成了,但是大家想想,水印有什么用?或者我们为什么要给页面加水印?答案是:防伪是的,我们的水印是用来防伪的,但是真的能像刚才那样防伪吗?让我们回忆一下我们刚才的水印思路:第一步:创建画布,绘制水印第二步:创建水印容器div标签第三步:将画布转化为图片链接,赋值给div标签的background-image样式属性步骤4:将水印容器div放在目标元素下,看似完成了水印功能,实则百废待兴!!!例如:1.查看修改容器div的background-image属性为空的元素2.查看删除容器div的元素。如果所有别有用心的人都做这两件事,这会导致我们刚刚在页面上制作的水印直接消失!!!所以我们要监控这些人的恶意行为,那么我们应该怎么做呢?MutationObserver来了!!!MutationObserverMutationObserver的具体用法可以在CDN上看到。这里我简单说一下它的作用:监控DOM元素的变化是的,它的作用就是:监控DOM元素的变化,所以他可以防止那些恶意用户破坏水印,因为我们刚才说了,恶意用户可以利用下面两种破坏水印的方法:1.查看元素修改容器div的background-image属性为空2.查看元素删除容器div两点都涉及DOM的修改,所以会引起MutationObserver的监听触发,所以我们可以使用MutationObserevr来监听这里使用了它的实例的两个方法:observe:开始监听DOM变化disconnect:停止监听DOM变化constwatermarkDirective:Directive={mounted(el,{value}){//接收styleStr,后面可以用来比较el。waterMarkStylest=drawWatermark(el,value)//首先定义一个MutationObserverel.observer=newMutationObserver(()=>{constinstance=document.getElementById(waterMarkId)conststyle=instance?.getAttribute('style')const{waterMarkStylestr}=el//修改样式||删除divif((instance&&style!==waterMarkStylest)||!instance){if(instance){//div还在,说明只修改样式instance.setAttribute('style',waterMarkStylestr)}else{//div不在,说明删除divdrawWatermark(el,value)}}})//开始监听el.observer.observe(document.body,{childList:true,attributes:true,subtree:true,})},unmounted(el){//当指定元素销毁时,记得停止监听el.observer.disconnect()el.observer=null},}现在,你修改风格e或者删除容器div,水印会重新生成,让恶意用户无法得逞!!!当然也可能有漏洞,大家可以指教!!结语我是林三鑫,一个狂热的前端菜鸟程序员。如果你有上进心,喜欢前端,想学前端,那我们可以交个朋友一起钓鱼。