Heim > Web-Frontend > js-Tutorial > Hauptteil

Wissen Sie, wie das Frontend Wasserzeichen implementiert?

醉折花枝作酒筹
Freigeben: 2021-07-30 16:57:50
nach vorne
2675 Leute haben es durchsucht

Bei der täglichen Arbeit stoßen wir oft auf viele sensible Daten. Um Datenlecks zu verhindern, müssen wir die Daten „verpacken“. Der Zweck besteht darin, diejenigen „kriminellen Elemente“, die an der Weitergabe von Daten interessiert sind, dazu zu bringen, ihr illegales Verhalten unter starkem „Druck der öffentlichen Meinung“ aufzugeben und sie zu „kriminellen Versuchen“ zu machen, um den Effekt zu erzielen, andere kampflos zu besiegen.

Diejenigen von uns, die in der Sicherheitsabteilung arbeiten, haben das Konzept der Datensicherheit bereits tief in den Knochen verankert. Bei jedem Text und jedem Bild muss darauf geachtet werden, ob die Gefahr von Datenlecks besteht Frage, über die wir nachgedacht haben. Beispielsweise ist das Wasserzeichen von Bildern ein Problem, mit dem wir in unserem Arbeitsprozess häufig konfrontiert werden. Da mein Jobinhalt die Entwicklung der Bewertungsplattform ist, erscheinen auf der Bewertungsplattform häufig einige riskante Bilder. Da das Sicherheitsbewusstsein der Prüfer uneinheitlich ist, ist es notwendig, den Bildern Wasserzeichen hinzuzufügen, um zu verhindern, dass unsichere Dinge passieren . von.

Analyse des Problems

In Anbetracht des Geschäftsszenarios besteht das Problem in dieser Phase lediglich darin, dass wir uns Sorgen über Datenlecks während des Überprüfungsprozesses machen. Derzeit berücksichtigen wir nur explizite Wasserzeichen, was bedeutet, dass etwas Text hinzugefügt wird Wörter zum Bild, die Ihre persönlichen Identitätsdaten unterscheiden können. Auf diese Weise können Einzelpersonen anhand der durchgesickerten Daten zurückverfolgt werden. Die wichtigste Funktion besteht natürlich darin, Vorkehrungen zu treffen und Probleme zu verhindern, bevor sie auftreten.

Lösen Sie das Problem

Implementierungsmethoden

Je nach der Aufteilung des Personals, das die Funktionen implementiert, können sie in Front-End-Wasserzeichen und Back-End-Wasserzeichen unterteilt werden Die Vorteile von Front-End-Wasserzeichen lassen sich in drei Punkten zusammenfassen: Erstens beanspruchen sie keine Serverressourcen und verlassen sich vollständig auf die Rechenleistung des Clients, wodurch der Druck auf den Server verringert wird. Zweitens ist es schnell, egal welche Front-End-Implementierung implementiert wird, die Leistung ist besser als die des Back-Ends. Drittens ist die Implementierung einfach. Der größte Vorteil der Implementierung von Wasserzeichen im Backend lässt sich auch in drei Punkten zusammenfassen: Sicherheit, Sicherheit und Sicherheit. Zhihu und Weibo verwenden beide Back-End-Wasserzeichenlösungen. Nach umfassender Überlegung übernehmen wir jedoch immer noch die Front-End-Lösung zur Implementierung von Wasserzeichen. Im Folgenden wird auch kurz vorgestellt, wie NodeJS das Wasserzeichen für Back-End-Bilder implementiert.

Knotenimplementierung

stellt drei NPM-Pakete bereit. Dieser Teil steht nicht im Mittelpunkt unseres Artikels, es wird nur eine einfache Demo bereitgestellt.

1, gm https://github.com/aheckmann/gm 6.4k star

const fs = require('fs');
const gm = require('gm');


gm('/path/to/my/img.jpg')
.drawText(30, 20, "GMagick!")
.write("/path/to/drawing.png", function (err) {
  if (!err) console.log('done');
});
Nach dem Login kopieren

Erfordert die Installation von GraphicsMagick oder ImageMagick;

2, Node-Images: https://github.com/zhangyuanwei/node- Bilder

const wrap = document.querySelector('#ReactApp');
const { clientWidth, clientHeight } = wrap;
const waterHeight = 120;
const waterWidth = 180;
// 计算个数
const [columns, rows] = [~~(clientWidth / waterWidth), ~~(clientHeight / waterHeight)]
for (let i = 0; i < columns; i++) {
    for (let j = 0; j <= rows; j++) {
        const waterDom = document.createElement(&#39;div&#39;);
        // 动态设置偏移值
        waterDom.setAttribute(&#39;style&#39;, `
            width: ${waterWidth}px; 
            height: ${waterHeight}px; 
            left: ${waterWidth + (i - 1) * waterWidth + 10}px;
            top: ${waterHeight + (j - 1) * waterHeight + 10}px;
            color: #000;
            position: absolute`
        );
        waterDom.innerText = &#39;测试水印&#39;;
        wrap.appendChild(waterDom);
    }
}
Nach dem Login kopieren

Keine Installation anderer Tools erforderlich, leichtgewichtig, entwickelt von zhangyuanwei Chinese, chinesische Dokumentation;

3, Jimp: https://github.com/oliver-moran/jimp

Kann mit GIFWrap verwendet werden, um GIF zu erstellen Wasserzeichen;

Front-End-Implementierung

1, Hintergrundbild implementiert Vollbild-Wasserzeichen

Sie können den Effekt auf der Seite mit persönlichen Informationen innerhalb und außerhalb von Alibaba überprüfen

Vorteile: Das Bild wird sicher vom Backend generiert ;

Nachteil: Es muss eine HTTP-Anfrage initiiert werden, um Bildinformationen zu erhalten;

Effektanzeige: Da es sich um ein internes System handelt, ist die Anzeige des Effekts nicht bequem.

2. DOM implementiert Vollbild-Wasserzeichen und Bild-Wasserzeichen.

Ermitteln Sie die Bildbreite und -höhe im Onload-Ereignis des Bildes, generieren Sie den Wasserzeichenbereich entsprechend der Bildgröße und blockieren Sie ihn auf der oberen Ebene des Bildes Der DOM-Inhalt ist das Kopieren von Wasserzeichen oder anderen Informationen. Der Vergleich der Implementierungsmethoden ist einfach.

const wrap = document.querySelector(&#39;#ReactApp&#39;);
const { clientWidth, clientHeight } = wrap;
const waterHeight = 120;
const waterWidth = 180;
// 计算个数
const [columns, rows] = [~~(clientWidth / waterWidth), ~~(clientHeight / waterHeight)]
for (let i = 0; i < columns; i++) {
    for (let j = 0; j <= rows; j++) {
        const waterDom = document.createElement(&#39;p&#39;);
        // 动态设置偏移值
        waterDom.setAttribute(&#39;style&#39;, `
            width: ${waterWidth}px; 
            height: ${waterHeight}px; 
            left: ${waterWidth + (i - 1) * waterWidth + 10}px;
            top: ${waterHeight + (j - 1) * waterHeight + 10}px;
            color: #000;
            position: absolute`
        );
        waterDom.innerText = &#39;测试水印&#39;;
        wrap.appendChild(waterDom);
    }
}
Nach dem Login kopieren

Vorteile: einfach und leicht zu implementieren;

Nachteile: Zu große oder zu viele Bilder beeinträchtigen die Leistung; Kommen wir ohne Umschweife direkt zum Code

useEffect(() => {
      // gif 图不支持
    if (src && src.includes(&#39;.gif&#39;)) {
      setShowImg(true);
    }
    image.onload = function () {
      try {
        // 太小的图不加载水印
        if (image.width < 10) {
          setIsDataError(true);
          props.setIsDataError && props.setIsDataError(true);
          return;
        }
        const canvas = canvasRef.current;
        canvas.width = image.width;
        canvas.height = image.height;
        // 设置水印
        const font = `${Math.min(Math.max(Math.floor(innerCanvas.width / 14), 14), 48)}px` || fontSize;
        innerContext.font = `${font} ${fontFamily}`;
        innerContext.textBaseline = &#39;hanging&#39;;
        innerContext.rotate(rotate * Math.PI / 180);
        innerContext.lineWidth = lineWidth;
        innerContext.strokeStyle = strokeStyle;
        innerContext.strokeText(text, 0, innerCanvas.height / 4 * 3);
        innerContext.fillStyle = fillStyle;
        innerContext.fillText(text, 0, innerCanvas.height / 4 * 3);
        const context = canvas.getContext(&#39;2d&#39;);
        context.drawImage(this, 0, 0);
        context.rect(0, 0, image.width || 200, image.height || 200);
           // 设置水印浮层
        const pattern = context.createPattern(innerCanvas, &#39;repeat&#39;);
        context.fillStyle = pattern;
        context.fill();
      } catch (err) {
        console.info(err);
        setShowImg(true);
      }
    };
    image.onerror = function () {
      setShowImg(true);
    };
  }, [src]);
Nach dem Login kopieren

Vorteile: reine Frontend-Implementierung, das per Rechtsklick kopierte Bild ist ebenfalls mit einem Wasserzeichen versehen;

Nachteil: GIF wird nicht unterstützt, das Bild muss domänenübergreifend unterstützen;

Effektanzeige: unten angegeben.

Methode 2: Die Leinwand generiert eine Wasserzeichen-URL und weist sie dem CSS-Hintergrundattribut zu

export const getBase64Background = (props) => {
  const { nick, empId } = GlobalConfig.userInfo;
  const {
    rotate = -20,
    height = 75,
    width = 85,
    text = `${nick}-${empId}`,
    fontSize = &#39;14px&#39;,
    lineWidth = 2,
    fontFamily = &#39;microsoft yahei&#39;,
    strokeStyle = &#39;rgba(255, 255, 255, .15)&#39;,
    fillStyle = &#39;rgba(0, 0, 0, 0.15)&#39;,
    position = { x: 30, y: 30 },
  } = props;
  const image = new Image();
  image.crossOrigin = &#39;Anonymous&#39;;
  const canvas = document.createElement(&#39;canvas&#39;);
  const context = canvas.getContext(&#39;2d&#39;);
  canvas.width = width;
  canvas.height = height;
  context.font = `${fontSize} ${fontFamily}`;
  context.lineWidth = lineWidth;
  context.rotate(rotate * Math.PI / 180);
  context.strokeStyle = strokeStyle;
  context.fillStyle = fillStyle;
  context.textAlign = &#39;center&#39;;
  context.textBaseline = &#39;hanging&#39;;
  context.strokeText(text, position.x, position.y);
  context.fillText(text, position.x, position.y);
  return canvas.toDataURL(&#39;image/png&#39;);
};

// 使用方式 
<img src="https://xxx.xxx.jpg" />
<p className="warter-mark-area" style={{ backgroundImage: `url(${getBase64Background({})})` }} />
Nach dem Login kopieren

Vorteile: reine Front-End-Implementierung, unterstützt domänenübergreifend, unterstützt Git-Bild-Wasserzeichen;

Nachteile: die generierte Base64-URL ist relativ groß;

Tatsächlich können Sie basierend auf diesen beiden Methoden für die erste Leinwandimplementierung leicht die dritte Methode finden, bei der bei der ersten Methode die obere Ebene des Bildes mit einer Nicht-Bild-Leinwand abgedeckt wird , sodass die Mängel der beiden Methoden perfekt vermieden werden können. Aber halten Sie einen Moment inne und denken Sie darüber nach. Gibt es eine einfachere und einfachere Möglichkeit, die beiden Lösungen zu kombinieren und Leinwand zum Zeichnen zu verwenden? Ja, verwenden Sie stattdessen SVG.

4, SVG-Methode (die derzeit verwendete Lösung)

liefert eine Reaktionsversion der Wasserzeichenkomponente.

export const WaterMark = (props) => {
  // 获取水印数据
  const { nick, empId } = GlobalConfig.userInfo;
  const boxRef = React.createRef();
  const [waterMarkStyle, setWaterMarkStyle] = useState(&#39;180px 120px&#39;);
  const [isError, setIsError] = useState(false);
  const {
    src, text = `${nick}-${empId}`, height: propsHeight, showSrc, img, nick, empId
  } = props;
  // 设置背景图和背景图样式
  const boxStyle = {
    backgroundSize: waterMarkStyle,
    backgroundImage: `url("data:image/svg+xml;utf8,<svg width=\&#39;100%\&#39; height=\&#39;100%\&#39; xmlns=\&#39;http://www.w3.org/2000/svg\&#39; version=\&#39;1.1\&#39;><text width=\&#39;100%\&#39; height=\&#39;100%\&#39; x=\&#39;20\&#39; y=\&#39;68\&#39;  transform=\&#39;rotate(-20)\&#39; fill=\&#39;rgba(0, 0, 0, 0.2)\&#39; font-size=\&#39;14\&#39; stroke=\&#39;rgba(255, 255, 255, .2)\&#39; stroke-width=\&#39;1\&#39;>${text}</text></svg>")`,
  };
  const onLoad = (e) => {
    const dom = e.target;
    const {
      previousSibling, nextSibling, offsetLeft, offsetTop,
    } = dom;
    // 获取图片宽高
    const { width, height } = getComputedStyle(dom);
    if (parseInt(width.replace(&#39;px&#39;, &#39;&#39;)) < 180) {
      setWaterMarkStyle(`${width} ${height.replace(&#39;px&#39;, &#39;&#39;) / 2}px`);
    };
    previousSibling.style.height = height;
    previousSibling.style.width = width;
    previousSibling.style.top = `${offsetTop}px`;
    previousSibling.style.left = `${offsetLeft}px`;
    // 加载 loading 隐藏
    nextSibling.style.display = &#39;none&#39;;
  };
  const onError = (event) => {
    setIsError(true);
  };
  return (
    <p className={styles.water_mark_wrapper} ref={boxRef}>
      <p className={styles.water_mark_box} style={boxStyle} />
      {isError
        ? <ErrorSourceData src={src} showSrc={showSrc} height={propsHeight} text="图片加载错误" helpText="点击复制图片链接" />
        : (
          <>
            <img onLoad={onLoad} referrerPolicy="no-referrer" onError={onError} src={src} alt="图片显示错误" />
            <Icon className={styles.img_loading} type="loading" />
          </>
        )
      }
    </p>
  );
};
Nach dem Login kopieren

Vorteile: Unterstützt GIF-Wasserzeichen, keine domänenübergreifenden Probleme, verwendet Wiederholungsattribute, kein Einfügen in den Dom-Prozess, keine Leistungsprobleme; das Wasserzeichen Okay, hat das Bild nicht kein Wasserzeichen?

Antwort:

Sie können MutationObserver verwenden, um den Wasserknoten zu überwachen.

Frage 2:

Klicken Sie mit der rechten Maustaste, um das Bild zu kopieren. Antwort: Die Rechtsklick-Funktion ist für alle Bilder deaktiviert

Frage 3:

Was passiert, wenn die Bildinformationen aus dem Netzwerk der Konsole bezogen werden?

Antwort:

Für diesen Vorgang gibt es derzeit keine gute Lösung. Es wird empfohlen, eine Back-End-Implementierungslösung zu verwenden

Zusammenfassung

Die im Frontend implementierte Wasserzeichenlösung ist immer nur eine vorübergehende Lösung, und die Implementierung im Geschäfts-Backend verbraucht Serverressourcen. Tatsächlich besteht die idealste Lösung darin, einen unabhängigen Wasserzeichendienst bereitzustellen eine leichte Verzögerung beim Ladevorgang. Im Vergleich zur Datensicherheit sind Verzögerungen im Millisekundenbereich immer noch akzeptabel, wodurch sichergestellt werden kann, dass die Servicestabilität des Unternehmens nicht beeinträchtigt wird.

Während des täglichen Frage-und-Antwort-Prozesses kommen auch viele Geschäftsparteien zu mir, um mit mir über die Risikopunkte der Wasserzeichen-Okklusion zu sprechen. Ich kann ihnen jedes Mal nur mit der Bedeutung der Datensicherheit antworten , und Dichte des Wasserzeichens Sie werden auch kontinuierlich optimiert. Ich glaube, dass es eine Version geben wird, die nicht nur als Wasserzeichen fungieren, sondern auch das Okklusionsproblem besser lösen kann.

Empfohlenes Lernen: HTML-Video-Tutorial

Das obige ist der detaillierte Inhalt vonWissen Sie, wie das Frontend Wasserzeichen implementiert?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:segmentfault.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage