Skip to content

BlindWatermark 加密隐形盲水印

c-blind-watermark 用于给敏感页面添加可溯源的隐形盲水印。组件会把服务端生成的短 token,或本地传入的 key/value 数据,编码成肉眼难以察觉的像素扰动,并重复铺满页面容器。发生截图或拍屏泄露后,可以把图片上传到配套服务端尝试解码,追溯对应用户或业务信息。组件会默认加入当前时间(精确到秒);客户端 IP 建议通过服务端 GET /watermark/client-info 获取后传入 clientIp

重要说明

opacity 只控制可见调试层,默认 0 表示不显示肉眼可见文字水印;真正写入截图的隐形水印由 strength 控制。如果把 strength 设为 0,截图里就不会有可恢复信息。

生产推荐

正式项目推荐使用服务端生成的短 token,前端只负责嵌入 token。真实用户信息、业务信息和密钥保存在服务端 PostgreSQL 中,避免把生产密钥暴露在浏览器。服务端生成 token 时会默认加入 watermarkTime 当前时间(精确到秒)和服务端识别到的 clientIp

关于本机 IP

现代浏览器出于隐私限制,无法可靠直接读取当前电脑本机 / 局域网 IP。组件提供 clientIp 属性,请通过服务端接口、登录态或业务系统获取后传入;本项目服务端提供 GET /watermark/client-info 返回服务端看到的客户端 IP。

基础用法(生产推荐)

动态配置预览

可以直接修改配置项查看水印覆盖、可见调试层和嵌入强度变化。生产环境通常保持 opacity = 0,这里只是为了观察效果默认打开调试层。

简单模式

如果只是内部 demo 或低安全要求场景,也可以直接传入 data + secretKey。组件会默认追加 watermarkTime 当前时间(精确到秒),并在浏览器端使用 Web Crypto 对数据加密后再嵌入。

vue
<c-blind-watermark
  :data="{
    userId: 'u_10001',
    userName: '张三',
    department: '研发部'
  }"
  secret-key="local-demo-secret"
>
  <SensitiveDashboard />
</c-blind-watermark>

注意

浏览器端密钥会出现在前端代码或运行环境中,不能作为生产级安全方案。正式项目请使用后端生成的 token

可见调试层

opacity 只影响可见调试文字,方便调试水印覆盖范围;真实隐形水印不受该值影响。

vue
<c-blind-watermark
  token="cwb1_xxx"
  debug-content="DEBUG WATERMARK"
  :opacity="0.12"
/>

服务端接口示例

获取服务端识别到的客户端 IP:

bash
curl http://localhost:3000/watermark/client-info

生成 token:

bash
curl -X POST http://localhost:3000/watermark/tokens \
  -H "Content-Type: application/json" \
  -d '{"data":{"userId":"u_10001","documentId":"doc_888"},"subject":"u_10001","purpose":"dashboard-trace"}'

验证 token:

bash
curl -X POST http://localhost:3000/watermark/tokens/verify \
  -H "Content-Type: application/json" \
  -d '{"token":"cwb1_xxx"}'

上传截图解码:

bash
curl -X POST http://localhost:3000/watermark/decode \
  -F "image=@screenshot.png"

API

Props

属性说明类型默认值
data简单模式水印信息,支持 key/valueRecord<string, string | number | boolean | null | Array>{}
secretKey简单模式浏览器端加密密钥,不建议生产使用String''
token服务端生成的短 token,优先级高于 data + secretKeyString''
clientIp客户端 IP。浏览器无法可靠直接读取,建议通过服务端接口获取后传入String''
strength真实隐形水印嵌入强度,值越大越容易解码,也越可能被肉眼察觉Number0.035
opacity可见调试层透明度,默认不显示可见文字水印Number0
tileSize重复水印块尺寸Number384
cellSize编码单元尺寸Number4
zIndex水印层级Number9
disabled是否禁用水印Booleanfalse
debugContent可见调试层文字,仅在 opacity > 0 时显示String | String[]''
maxPayloadBytes最大 payload 字节数,过长会影响截图解码成功率Number128
tamperProtect是否启用轻量防篡改检测Booleantrue

Events

事件名说明回调参数
ready盲水印图案生成后触发{ payloadBytes, tileSize, cellSize }
error生成失败时触发{ code, message }
change水印层被删除或修改时触发Event

Expose

方法名说明类型
regenerate手动重新生成盲水印() => Promise<void>
getPayload获取当前嵌入的 payload/token() => string
getPatternUrl获取当前盲水印 tile 的 dataURL() => string

Slots

插槽名说明
default需要添加隐形盲水印的页面内容

局限性

盲水印用于泄露溯源,不是 DRM,不能阻止截图、裁剪、压缩、模糊、重绘或恶意去除。首版算法主要面向浏览器/系统截图;手机拍屏受透视、摩尔纹、压缩、模糊、反光和低光照影响,解码结果应以置信度为准。