使用Web Component实现防篡改水印

 更新时间:2023年12月20日 08:18:24   作者:程序员Alvin  
Web Component内部有钩子天然支持被篡改时被触发,用来防篡改非常方便,所以本文就将使用Web Component实现防篡改水印,感兴趣的小伙伴可以了解下

这篇文章的关键可以分为3个部分,Web Component + 防篡改 + 水印生成。在使用Web Component之前,我已经通过MutationObserver实现了防篡改水印的第一版。但在了解到Web Component的特性之后,我认为也许用Web Component也不错,因为Web Component内部有钩子天然支持被篡改时被触发,用来防篡改非常方便。下面也会对MutationObserver与Web Component的实现做比较。

设计目标

设计一个hook用于插入水印至ref指定的组件中,被插入的水印节点应当不可篡改。

const { data: username } = useRequest(...)
const ref = useWatermark(username); // 水印组件会插入ref.current对应的DOM节点

return <div ref={ref}>
    {children}
</div>

水印生成原理

创建一个div节点,将背景设置为一个透明的水印图片,将z-index设置为10000叠加在站点上即可实现水印效果。

生成水印图

水印图可以在前端直接生成,可以使用canvas通过命令绘制,或预声明svg字符串。我选用的是svg字符串生成,因为使用svg清晰度较高,也比较简单。将svgString定义好,再转换成base64即可

        const svgString = `<svg xmlns="http://www.w3.org/2000/svg" width="400px" height="146px">
        <text x="10px" y="73px"
            text-anchor="start"
            transform="rotate(-20 0 73)"
            fill="rgba(40, 47, 56, 0.03)"
            font-weight="500"
            font-size="14"
            font-family="Helvetica Neue,Helvetica,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,WenQuanYi Micro Hei,sans-serif"
        >
            ${content}
        </text>
        <text x="210px" y="146px"
            text-anchor="start"
            transform="rotate(-20 200 146)"
            fill="rgba(40, 47, 56, 0.03)"
            font-weight="500"
            font-size="14"
            font-family="Helvetica Neue,Helvetica,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,WenQuanYi Micro Hei,sans-serif"
        >
            ${content}
        </text>
    </svg>`;
        const background = 'data:image/svg+xml;base64,' + window.btoa(svgString);

image

CSS与DIV布局

注意所有CSS都应该直接定义在div节点上,并且加上!important,这样能有效避免样式被覆盖。

position: absolute !important; 
top: 0px !important; 
right: 0px !important; 
bottom: 0px !important; 
left: 0px !important; 
overflow: hidden !important; 
display: block !important; 
opacity: 1 !important; 
z-index: 10000 !important; 
pointer-events: none !important; // 可以防止鼠标事件被水印节点拦截
background: url(${background});
const node = document.createElement('div');
watermarkRef.current = node;
node.setAttribute(
    'style',
    `position: absolute !important; top: 0px !important; right: 0px !important; bottom: 0px !important; left: 0px !important; overflow: hidden !important; display: block !important; opacity: 1 !important; z-index: 10000 !important; pointer-events: none !important; background: url(${background});`
);

防篡改原理

MutationObserve

const observer = new MutationObserver(function (entries) {
    // 因为MutationObserve没办法监听自己的属性是否被修改,自己是否被移除,只能监听父组件
    // 通过对父组件观测,entry.type = 'attributes'可以判断水印节点的属性是否被修改
    // entry.type = 'childList' 可以判断水印节点是否被移除
    for (const entry of entries) {
        if (
            (entry.type === 'attributes' && entry.target === watermarkRef.current) ||
            (entry.type === 'childList' && Array.from(entry.removedNodes).includes(watermarkRef.current))
        ) {
            removeWatermark();
            generateWaterMark();
            return;
        }
    }
});

const config = { attributes: true, childList: true, subtree: true };
observer.observe(
    parentNode, // 水印挂载到的父组件
    config
);

Web Component

使用Web Component的好处就是可以直接绑定回调函数,检测自己是否被篡改或移除。

class WatermarkElement extends HTMLElement {
  static observedAttributes = ["style"]; // 需要观测的属性

  constructor() {
    super();
  }

  connectedCallback() {
    // 当组件挂载至dom中,可以用来初始化
  }

  disconnectedCallback() {
    // 当组件从document中移除,用于检测水印被删除
  }

  adoptedCallback() {
    // 当组件在document中被移动
    // 若触发则表示水印被移动,可能失效
  }

  attributeChangedCallback(name, oldValue, newValue) {
    // 若触发表示style属性被操作,可能是恶意篡改
  }
}

customElements.define("watermark-element", MyCustomElement);

到此这篇关于使用Web Component实现防篡改水印的文章就介绍到这了,更多相关Web Component防篡改水印内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • javascript 去字符串空格终极版(支持utf8)

    javascript 去字符串空格终极版(支持utf8)

    其实空格有两个,一个ASCII编号是32,另一个是ASCII编号是160.后者是unicode编码。以前写一个贴子ie6下准确判断空格还以是IE6不能正确判断空格。
    2009-11-11
  • JS实现仿苹果底部任务栏菜单效果代码

    JS实现仿苹果底部任务栏菜单效果代码

    这篇文章主要介绍了JS实现仿苹果底部任务栏菜单效果代码,可实现鼠标滑过显示大图标功能,涉及javascript鼠标事件及页面元素遍历并修改属性的技巧,需要的朋友可以参考下
    2015-08-08
  • js实现微博发布小功能

    js实现微博发布小功能

    本篇文章主要介绍了javascript实现微博发布小功能的示例代码,具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • js文件中引入另一个js文件的4种方法总结

    js文件中引入另一个js文件的4种方法总结

    JavaScript文件是一个文本类型的文件,在任何文本编辑器中都可以被打开和编辑,JavaScript文件的扩展名为js,这篇文章主要给大家介绍了关于js文件中引入另一个js文件的4种方法总结,需要的朋友可以参考下
    2023-12-12
  • webpack结合express实现自动刷新的方法

    webpack结合express实现自动刷新的方法

    这篇文章主要给大家介绍了关于webpack结合express实现自动刷新的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用webpack具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-05-05
  • javascript编程开发中取色器及封装$函数用法示例

    javascript编程开发中取色器及封装$函数用法示例

    这篇文章主要介绍了javascript编程开发中取色器及封装$函数,结合实例形式分析了javascript封装$函数及数值运算、页面元素动态操作实现取色器功能相关技巧,需要的朋友可以参考下
    2017-08-08
  • document.addEventListener使用介绍

    document.addEventListener使用介绍

    这篇文章主要介绍了document.addEventListener,下面有个示例,大家可以参考下
    2014-03-03
  • 浅析JavaScript中命名空间namespace模式

    浅析JavaScript中命名空间namespace模式

    namespace即“命名空间”,也称“名称空间” 、”名字空间”。接下来通过本文给大家介绍JavaScript中命名空间namespace模式的相关知识,非常不错,具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-06-06
  • 原生JavaScript实现刮刮乐

    原生JavaScript实现刮刮乐

    这篇文章主要为大家详细介绍了原生JavaScript实现刮刮乐,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-09-09
  • 用JS控制表格的逐行变色的表单

    用JS控制表格的逐行变色的表单

    给大家分享一个我写的友好的表单,可以用来代替gridview生成的默认的表格(那个控件生成的垃圾代码太多).
    2008-02-02

最新评论