web前端水印方案

web前端水印方案

前言

在 Web 开发中,水印是一种常见的安全措施,用于保护内容的版权和防止非法复制。本文将介绍一种基于 JavaScript 的 Web 前端水印方案,包括水印的生成和动态更新机制。

前端水印方案有那些

css 背景图水印

最简单的水印方式

css 复制代码
 .watermark-box {
        width: 100%;
        height: 100vh;
        background-image: url('watermark.png');
    }

SVG 水印

SVG:可缩放矢量图形,是一种基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式

创建一个 watermark.svg

arduino 复制代码
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <text x="0" y="30" fill="#000000" font-size="20" font-family="Arial" opacity="0.3" transform="rotate(-10)">
    测试水印
  </text>
</svg>
css 复制代码
body {
        background-image: url('./watermark.svg');
        background-repeat: repeat;
        background-position: center;
        background-size: 100px 50px;
    }
  1. 宽高限制水印的大小 这里为100*100的水印

  2. 显示文本需要用到text标签

  3. xy 属性定义了文本左上角的坐标,即文本的起始点位置

  4. font-size 属性定义了文本的字体大小,以像素为单位。

  5. fill 属性定义了文本的颜色。

  6. transform 控制 x,y 轴的偏移和旋转角度 一般水印都会有一些倾斜。

批量复制 dom 实现水印

创建一个遮罩容器 根据可视容器的宽度和高度计算需要多少个小水印 可以动态生成水印内容

缺点重复生成 dom,不是很优雅

xml 复制代码
<!DOCTYPE html>
<html lang="en">
​
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
​
<style>
    #watermark-box {
        width: 100%;
        height: 100vh;
        position: absolute;
        z-index: -1;
        top: 0;
        left: 0;
        display: flex;
        flex-wrap: wrap;
        padding: 0;
        margin: 0;
    }
​
    .watermark-item {
        transform: rotate(-30deg);
        opacity: 0.2;
    }
</style>
​
<body>
    <div id="watermark-box"></div>
    <div>我是正文我是正文我是正文我是正文我是正文我是正文我是正文我是正文我是正文我是正文</div>
</body>
​
<script>
    function initWaterMark(text,el) {
        const waterHeight = 100
        const waterWidth = 100
        const { clientWidth, clientHeight } =
            document.documentElement || document.body
        const column = Math.ceil(clientWidth / waterWidth)
        const rows = Math.ceil(clientHeight / waterHeight)
        for (let i = 0; i < column * rows; i++) {
            const wrap = document.createElement('div')
            wrap.setAttribute('class', 'watermark-item')
            wrap.style.width = waterWidth + 'px'
            wrap.style.height = waterHeight + 'px'
            wrap.textContent = text
            el.appendChild(wrap)
        }
    }
    window.onload = () => {
        const el = document.getElementById("watermark-box")
        initWaterMark('测试水印',el)
    }
</script>
​
</html>

canvas+伪类

xml 复制代码
<!DOCTYPE html>
<html lang="en">
​
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
​
</style>
​
<body>
    <div class="watermark-box">
        <div>我是正文我是正文我是正文我是正文我是正文我是正文我是正文我是正文我是正文我是正文</div>
    </div>
</body>
​
<script>
​
    function createBackgroundImage(options) {
        const { content, H, W } = options;
        const canvas = document.createElement('canvas'); // 创建画布
        const ctx = canvas.getContext('2d');
        canvas.width = H;
        canvas.height = W;
        if (ctx) {
            ctx.rotate(-0.3); // 旋转文字
            ctx.fillStyle = 'rgba(0,0,0,0.2)'; // 设置字体颜色
            ctx.font = '40px'; // 设置字体的大小
            ctx.fillText(content, 30, 30);// 填充水印内容
        }
        return canvas.toDataURL('image/png'); // 转换成dataURL,可以直接设置成背景图片
    };
​
    function getWaterMark({ content, className, H = 120, W = 120, }) {
        const dataURL = createBackgroundImage({ content, H, W });
        // 设置伪类样式
        const defaultStyle = document.createElement('style');
        defaultStyle.innerHTML = `.${className}::after {
                content: '';
                display: block;
                width: 100%;
                height: 100vh;
                background-image: url(${dataURL});
                background-repeat: repeat;
                pointer-events: none;
                position: fixed;
                top: 0;
                left: 0;
            }`;
        document.head.appendChild(defaultStyle);
    };
​
​
    window.onload = () => {
        getWaterMark({
            content: "测试水印",
            className: 'watermark-box',
        });
    }
​
​
</script>
​
</html>

SVG+伪类

同 canvas+伪类 相同 只需要替换 canvas 绘制的水印变成 svg 绘制的即可

arduino 复制代码
​
    function getWaterMark({ content, className, H = 120, W = 120, }) {
        //....
​
        const svgStr = `<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
               <text x="0" y="30" fill="#000000" font-size="20" font-family="Arial" opacity="0.3" transform="rotate(-10)">
                 ${content}
               </text>
              </svg>`
        const dataURL = 'data:image/svg+xml;base64,'window.btoa(unescape(encodeURIComponent(svgStr)));
      
      //....
    };

水印安全

Shadow DOM

随着 Web 程序规模的增长,很容易遇到样式和逻辑冲突的问题。为了解决这些问题,Web 标准引入了 Shadow DOM,可以帮助我们更好地隔离和封装组件。Shadow DOM 是 Web Components 标准的一部分,是 Web Components 中的一个关键技术。它提供了一种将 HTML 结构、样式和行为封装在一个独立的、封闭的 DOM 中的机制。这意味着,使用 Shadow DOM 可以将组件的样式和结构隐藏在组件作用域内,防止其与全局样式或逻辑发生冲突。

所以可以把水印元素放在 Shadow DOM 中,从而在一定程度上防止篡改。

基本使用方法

使用 Element.attachShadow() 方法来将一个 shadow root 附加到任何一个元素上。

它接受一个配置对象作为参数,该对象有一个 mode 属性,值可以是 open 或者 closed

open 表示可以通过页面内的 JavaScript 方法来获取 Shadow DOM

closed 则表示不可以从外部获取 Shadow DOM

例子:

ini 复制代码
 const el = document.getElementById("watermark-box")
 const shadowRoot = el.attachShadow({ mode: 'closed' })

MutationObserver

MutaitionObserver 的作用主要是用于监听当前页面的 dom 变化情况,当所监听的 dom 发生变化时,可以通过回调函数做出响应,适用于我们希望得知当前页面的 dom 元素在何时发生了什么样的变化。

水印作为背景图 设置为style 样式 监听背景图是否被修改 如果被修改则 重新生成水印

php 复制代码
  function initMutationObserver(container) { 
        var mutation = new MutationObserver((mutationsList) => {
            for (let mutation of mutationsList) {
                if (mutation.type === 'attributes' && mutation.attributeName === 'style') {
                    getWaterMark({
                        content: "测试水印",
                        className: 'watermark-box',
                    });
                }
            }
        });
​
        // 安装监听
        mutation.observe(container, {
            childList: true,
            attributes: true,
            characterData: true,
            subtree: true,
            attributeOldValue: true,
            characterDataOldValue: true,
            attributeFilter: ['class', 'style']
​
        });
​
    }
    const container = document.querySelector(".watermark-box");
    initMutationObserver(container);
​

总结

以上几种前端水印方案可以根据自己的需要进行选择,web 水印可以保护页面内容的版权和完整性,防止被篡改和盗用。但是不存在绝对安全的前端水印方案。前端水印只是防范的一种手段,对于重要和敏感的内容,还需要结合其他保护措施来综合保护。

参考文档

blog.csdn.net/xgangzai/ar...

segmentfault.com/a/119000004...

推荐阅读

ARM架构下部署StarRocks3

Spring Validation实践及其实现原理

ThreadPoolExecutor杂谈

浅谈软件架构

你是否真的需要实现一个3D地图

招贤纳士

政采云技术团队(Zero),Base 杭州,一个富有激情和技术匠心精神的成长型团队。规模 500 人左右,在日常业务开发之外,还分别在云原生、区块链、人工智能、低代码平台、中间件、大数据、物料体系、工程平台、性能体验、可视化等领域进行技术探索和实践,推动并落地了一系列的内部技术产品,持续探索技术的新边界。此外,团队还纷纷投身社区建设,目前已经是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等众多优秀开源社区的贡献者。

如果你想改变一直被事折腾,希望开始折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊......如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的技术团队的成长过程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 zcy-tc@cai-inc.com

微信公众号

文章同步发布,政采云技术团队公众号,欢迎关注

相关推荐
vvw&1 小时前
如何在 Ubuntu 22.04 上安装 Caddy Web 服务器教程
linux·运维·服务器·前端·ubuntu·web·caddy
落日弥漫的橘_3 小时前
npm run 运行项目报错:Cannot resolve the ‘pnmp‘ package manager
前端·vue.js·npm·node.js
梦里小白龙3 小时前
npm发布流程说明
前端·npm·node.js
No Silver Bullet3 小时前
Vue进阶(贰幺贰)npm run build多环境编译
前端·vue.js·npm
破浪前行·吴4 小时前
【初体验】【学习】Web Component
前端·javascript·css·学习·html
泷羽Sec-pp4 小时前
基于Centos 7系统的安全加固方案
java·服务器·前端
IT 古月方源5 小时前
GRE技术的详细解释
运维·前端·网络·tcp/ip·华为·智能路由器
myepicure8885 小时前
Windows下调试Dify相关组件(1)--前端Web
前端·llm
用户59594399272195 小时前
大牛工程师告诉你:开关电源“Y电容”都是这样计算的!
前端
用户59594399272195 小时前
松下功率继电器HE-A全新登场
前端