29
头图

Write in front

Hello everyone, I’m Carey, welcome to follow my "blog" , all good things.

The "front-end watermark anti-tampering" method discussed in this article was originally intended to be submitted to the company as a patent, but before I wrote the pen, I searched it on a domestic patent search website and found that the exact same solution had already been applied for. It was submitted by a ByteDance buddy at the beginning of this year.

Now that the pit has been occupied, then I will not roll it.

But considering that this solution is simple and effective, share it with everyone here.

Implementation scheme of watermarking

The demand for front-end watermarking has always existed. The most frequent scenario is the company's internal system to prevent information leakage. If the implementation is placed on the front end, the mainstream implementation methods are divided into the following two categories:

  • SVG / PNG and other images combined with CSS background property
  • Canvas

For example, opening a well-known online material editing website to view the realization of its watermark is the first one.

截屏2021-10-10_11.50.42.png

Good guy, there are so many important , enough to see that the front-end writing style attaches great importance to this watermark.

Here I only took a screenshot of the CSS, and the corresponding HTML is a div element with a background image specified.

Another kind of watermark based on Canvas is not difficult to understand, just draw it directly, so I won't repeat it here.

Cracking the watermark

The front end years are quiet, until Devtools is opened by someone...

Once the developer tool of the browser is opened, the watermark on the page is directly broken by directly modifying the CSS properties of the element.

If it is a watermark based on Canvas, it seems more difficult to deal with, but in fact, if the entire Canvas element is violently deleted directly in the element area of the console, the watermark will no longer exist.

Anti-cracking watermark

Recall the watermark cracking solution mentioned earlier, either by modifying the CSS properties of the element or directly modifying the DOM structure, so can you try to influence the user with love to prevent him from modifying it? Of course not. There is a principle in human-computer interaction that "use the greatest maliciousness to guess your users."

But think about it carefully. Whether users modify CSS or modify DOM, they must open the browser's devtools. Can users not be allowed to open devtools?

sure.

Prevent users from opening devtools

Take windows as an example. If a user wants to open the console, there are two ways:

  1. Keyboard F12
  2. Right-click and select check element

This is easy:

// 阻止 F12 事件
document.addEventListener('keydown', event => {
    return 123 !== event.keyCode || event.returnValue = false;
});

// 阻止鼠标右键事件
document.addEventListener('contextmenu', event => {
    return event.returnValue = false;
});

This can indeed completely stop users who are trying to open devtools, but it is a bit simple and rude. After all, after the right mouse button, there are some other browser functions besides "checking elements". Too "one size fits all" will hurt the user experience.

Listen to the open event of devtools

Unfortunately, the browser does not provide a native devtools open event, but we can save the country by curve: through customs, check the difference between the browser's visible area and the browser window to determine whether the user has opened devtools. In fact, the open source solution devtools-detect 1.5k+ stars on Github did just that.

The core implementation is also very simple:

const resize = () => {
    const threshold = 200;
    const width = window.outerWidth - window.innerWidth > threshold;
    const height = window.outerHeight - window.innerHeight > threshold;
    if (width || height) {
        console.log('控制台打开了,用户准备破解水印了!!!');
    }
}

resize();
window.addEventListener('resize', resize);

However, this solution has a big loophole: it can only be used to detect when devtools is opened embedded in the browser page, but almost all browsers now provide the function of opening devtools in a new window, so this detection is very Easily bypassed.

截屏2021-10-10_13.08.05.png

MutationObserver

That's it, it's time to come up with the most difficult solution (the patented solution I mentioned at the beginning): the element attribute change monitoring based on MutationObserver.

The MutationObserver interface provides the ability to watch for changes being made to the DOM tree. It is designed as a replacement for the older Mutation Events feature, which was part of the DOM3 Events specification.

In short, MutationObserver can monitor the changes of any attribute on the DOM element, and if necessary, it can also monitor the changes of its child elements. Isn't this what we need?

When the user modifies the attribute of the watermark element through devtools, MutationObserver can notify us in time, so that we can restore our watermark in the first time. One thing to note is that what MutationObserver monitors is the attribute of the element, which is attributes , so our css style should be embedded in the HTML style

The following code is the concrete realization of this scheme:

// <h1 style="margin:100px;">别改我</h1>

const options = {
    childList: true,
    attributes: true,
    subtree: true,
    attributesOldValue: true,
    characterData: true,
    characterDataOldValue: true,
}

const reset = (expression = () => {}) => {
    setTimeout(() => {
      observer.disconnect();
    // 执行恢复方法
        expression();
    observer.observe(h1, options);
   }, 0);
}

const callback = (records) => {
    const record = records[0];
  if (record.type === 'attributes' && record.attributeName === 'style') {
      reset(() => {
        h1.setAttribute('style', 'margin:100px;');
    });
  } else if (record.type === 'characterData') {
      reset(() => {
        h1.textContent = '别改我'  
    });
  }
}

const observer = new MutationObserver(callback);
observer.observe(h1, options);

The picture shows that it is forbidden to modify the style and textContent of the h1 element, which can be copied directly to the IDE to play.

Here you can directly extract the value of style as a constant, but whenever the user modifies the style attribute of an element, this code will automatically overwrite the modified value of the user with the fixed constant just now, thus realizing the tamper-proof front-end watermark.

finally

Welcome everyone to add my "K-I2ving" make friends, and I can also help with internal recommendations (any well-known company in Shenzhen will do).
It is recommended to follow my "blog" , which is all good things.


劉凯里
841 声望1.6k 粉丝

我可能是一个假前端