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;
}
宽高限制水印的大小 这里为100*100的水印
显示文本需要用到text标签
x
和y
属性定义了文本左上角的坐标,即文本的起始点位置
font-size
属性定义了文本的字体大小,以像素为单位。
fill
属性定义了文本的颜色。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 水印可以保护页面内容的版权和完整性,防止被篡改和盗用。但是不存在绝对安全的前端水印方案。前端水印只是防范的一种手段,对于重要和敏感的内容,还需要结合其他保护措施来综合保护。
参考文档
segmentfault.com/a/119000004...
推荐阅读
招贤纳士
政采云技术团队(Zero),Base 杭州,一个富有激情和技术匠心精神的成长型团队。规模 500 人左右,在日常业务开发之外,还分别在云原生、区块链、人工智能、低代码平台、中间件、大数据、物料体系、工程平台、性能体验、可视化等领域进行技术探索和实践,推动并落地了一系列的内部技术产品,持续探索技术的新边界。此外,团队还纷纷投身社区建设,目前已经是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等众多优秀开源社区的贡献者。
如果你想改变一直被事折腾,希望开始折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊......如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的技术团队的成长过程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 zcy-tc@cai-inc.com
微信公众号
文章同步发布,政采云技术团队公众号,欢迎关注