泄密怎么办,当然是加水印咯

2,931 阅读2分钟

源码地址(admin分支)

方案

1.生成重复元素

把水印容器元素position:fixed,覆盖到需要打水印的区域,区域里面重复生成水印元素,设置透明度。设置pointer-events: none; 点击穿透功能。

主要用到 document的元素操作api。

2.设置背景图片

在上一种方法的基础上,把元素去掉,把水印容器元素的背景图片设置为水印。图片可以用canvas生成。

3.MutationObserver 优化

MutationObserver监听dom树更改,当我们调试删除元素、修改样式时可触发。重新生成水印即可。用vue2自定义指令封装水印,全部代码如下。

const globalCanvas = null
const globalWaterMark = null

// watermark 样式
let style = `
display: block;
overflow: hidden;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-repeat: repeat;
pointer-events: none;`

const getDataUrl = ({
  font,
  fillStyle,
  textAlign,
  textBaseline,
  text
}) => {
  font = font || '16px normal'
  fillStyle = fillStyle || 'rgba(180, 180, 180, 0.2)'
  text = text || ''
  const rotate = -20
  const canvas = globalCanvas || document.createElement('canvas')
  const ctx = canvas.getContext('2d') // 获取画布上下文

  ctx.rotate((rotate * Math.PI) / 180)
  ctx.font = font
  ctx.fillStyle = fillStyle
  ctx.textAlign = textAlign || 'left'
  ctx.textBaseline = textBaseline || 'middle'
  ctx.fillText(text, canvas.width / 10, canvas.height / 2)

  return canvas.toDataURL('image/png')
}

const setWaterMark = (el, binding) => {
  const parentElement = el.parentElement

  // 获取对应的 canvas 画布相关的 base64 url
  const url = getDataUrl(binding)

  // 创建 waterMark 父元素
  const waterMark = globalWaterMark || document.createElement('div')
  waterMark.className = 'water-mark' // 方便自定义展示结果
  style = `${style}background-image: url(${url});`
  waterMark.setAttribute('style', style)

  // 将对应图片的父容器作为定位元素
  parentElement.setAttribute('style', 'position: relative;')

  // 将图片元素移动到 waterMark 中
  parentElement.appendChild(waterMark)
}

// 监听 DOM 变化
const createObserver = (el, binding) => {
  const waterMarkEl = el.parentElement.querySelector('.water-mark')

  const observer = new MutationObserver((mutationsList) => {
    if (mutationsList.length) {
      const { removedNodes, type, target } = mutationsList[0]
      const currStyle = waterMarkEl.getAttribute('style')
      // 证明被删除了
      if (removedNodes[0] === waterMarkEl) {
        observer.disconnect()
        init(el, { value: binding })
      } else if (
        type === 'attributes'
        && target === waterMarkEl
        && currStyle !== style
      ) {
        waterMarkEl.setAttribute('style', style)
      }
    }
  })

  observer.observe(el.parentElement, {
    childList: true,
    attributes: true,
    subtree: true
  })
}

// 初始化
const init = (el, binding) => {
  // 设置水印
  setWaterMark(el, binding.value)
  // 启动监控
  createObserver(el, binding.value)
}

// 定义指令配置项
const directives = {
  inserted(el, binding) {
    init(el, binding)
  }
}

export default {
  name: 'watermark',
  directives
}

其他

还有一种修改rgb值的水印方案,当然了,其他平台类似,还有各种方式去掉水印,现有的方案都不是完美的 debugger时,disable javascript不启用js,都可以去掉水印。

f12 及 鼠标右击处理

document.addEventListener('keydown', function(e) {
    if (e.key === 'F12') {
  	 e.preventDefault()
		}
})
  // 阻止菜单右键
document.addEventListener('contextmenu', function(event) {
    event.preventDefault()
})

参考

你知道前端水印功能是怎么实现的吗