preface

Hello everyone, I am Lin Sanxin, with the most easy to understand the most difficult knowledge points is my motto, the basis is advanced premise is my initial mind

background

We usually in the development or in the interview, will inevitably encounter a problem — to the page watermarking, in fact, this is not difficult, but there are some points to pay attention to, so the seemingly simple function, to try to do:

  • 1. Rigor
  • 2. Security

To implement the watermark

In fact, it is not difficult to achieve watermark, just need to use the custom command + canvas + background-image, it is also very convenient to achieve:

import type { Directive, App } from 'vue'interface Value { font? : string textColor? : string text? : string }const waterMarkId = 'waterMark'
const canvasId = 'can'

const drawWatermark = (el, value: Value) = > {
  const {
    font = '16px Microsoft JhengHei',
    textColor = 'rgba (180, 180, 180, 0.3)',
    text = 'Three Hearts',
  } = value
  // Create a canvas tag
  const canvas = document.getElementById(canvasId) as HTMLCanvasElement
  // If it already exists, it will not be created
  const can = canvas || document.createElement('canvas')
  can.id = canvasId
  el.appendChild(can)
  // Set width and height
  can.width = 400
  can.height = 200
  / / not visible
  can.style.display = 'none'
  const ctx = can.getContext('2d')!
  // Set the canvas style
  ctx.rotate((-20 * Math.PI) / 180)
  ctx.font = font
  ctx.fillStyle = textColor
  ctx.textAlign = 'left'
  ctx.textBaseline = 'middle'
  ctx.fillText(text, can.width / 3, can.height / 2)

  // The watermark container
  const waterMaskDiv = document.createElement('div')
  waterMaskDiv.id = waterMarkId
  // Sets the container's property style
  // Convert the canvas content you just generated into an image and assign it to the container's background-image style
  const styleStr = `
    width: 100%;
    height: 100%;
    position: fixed;
    z-index: -1;
    top: 0;
    left: 0;
    pointer-events: none;
    background-image: url(${can.toDataURL('image/png')})
  `
  waterMaskDiv.setAttribute('style', styleStr)

  // Place the watermark container under the target element
  el.appendChild(waterMaskDiv)

  return styleStr
}

const watermarkDirective: Directive = {
  mounted(el, { value }) {
    // Receive styleStr, which can be used later for comparison
    el.waterMarkStylestr = drawWatermark(el, value)
  }
}
Copy the code

Use it directly as v-watermark:

<div 
    v-watermark={text: 'watermark name ', textColor:' rGBA (180, 180, 180, 0.3)'}
  >
Copy the code

The results are as follows:

Malicious modification

We have completed the watermark function, but let’s think about it, what is the use of watermark? Or why do we watermark a page? The answer is: anti-counterfeiting

Yes, our watermarks are for security purposes, but is doing what we just did really anti-counterfeiting? Let’s recall our previous watermarking idea:

  • The first step: Create a canvas and paint the watermark
  • The second stepCreate a watermark container div tag
  • The third step: assigns the canvas canvas to image link to the background-image attribute of the div tag
  • The fourth step: Puts the watermark container div under the target element

It seems to complete the watermark function, but in fact there are many flaws!! Such as:

  • 1. The review element changes the background-image property of the container div to empty

  • Delete the container div from the review element

If all people with ulterior motives do these two things, it will cause the watermark we just made on the page to disappear!!

So we need to monitor these people for malicious behavior. So how? Here comes the MutationObserver!!

MutationObserver

The MutationObserver is used to monitor changes in DOM elements

Yes, it monitors changes in the DOM elements, so it prevents malicious users from breaking watermarks, because as we’ve just said, malicious users can do so in two ways:

  • 1. The review element changes the background-image property of the container div to empty
  • Delete the container div from the review element

Both of them involve DOM modification, so they will trigger the monitoring of MutationObserver, so we can use MutationObserevr to monitor. There are two methods used on its instance:

  • observe: Enables monitoring DOM changes
  • disconnect: Stops monitoring DOM changes
const watermarkDirective: Directive = {
  mounted(el, { value }) {
    // Receive styleStr, which can be used later for comparison
    el.waterMarkStylestr = drawWatermark(el, value)
    // Define a MutationObserver
    el.observer = new MutationObserver(() = > {
      const instance = document.getElementById(waterMarkId)
      conststyle = instance? .getAttribute('style')
      const { waterMarkStylestr } = el
      / / modify the style | | delete div
      if((instance && style ! == waterMarkStylestr) || ! instance) {if (instance) {
          // the div is still there
          instance.setAttribute('style', waterMarkStylestr)
        } else {
          // if div is not present, it is deleted
          drawWatermark(el, value)
        }
      }
    })
    // Start monitoring
    el.observer.observe(document.body, {
      childList: true.attributes: true.subtree: true,}}),unmounted(el) {
    // When specifying element destruction, remember to stop monitoring
    el.observer.disconnect()
    el.observer = null}},Copy the code

Now, if you change the style or delete the container div, the watermark will be generated again, so malicious users can not succeed!! Of course there may be loopholes, we can give advice!!

conclusion

I am Lin Sanxin, an enthusiastic front-end novice programmer. If you progress, like the front end, want to learn the front end, then we can make friends, touch fish ha ha, touch fish, point this –> touch fish boiling point