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.
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.
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'); });
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('div'); // 动态设置偏移值 waterDom.setAttribute('style', ` 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 = '测试水印'; wrap.appendChild(waterDom); } }
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('#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('p'); // 动态设置偏移值 waterDom.setAttribute('style', ` 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 = '测试水印'; wrap.appendChild(waterDom); } }
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('.gif')) { 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 = 'hanging'; 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('2d'); context.drawImage(this, 0, 0); context.rect(0, 0, image.width || 200, image.height || 200); // 设置水印浮层 const pattern = context.createPattern(innerCanvas, 'repeat'); context.fillStyle = pattern; context.fill(); } catch (err) { console.info(err); setShowImg(true); } }; image.onerror = function () { setShowImg(true); }; }, [src]);
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 = '14px', lineWidth = 2, fontFamily = 'microsoft yahei', strokeStyle = 'rgba(255, 255, 255, .15)', fillStyle = 'rgba(0, 0, 0, 0.15)', position = { x: 30, y: 30 }, } = props; const image = new Image(); image.crossOrigin = 'Anonymous'; const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); 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 = 'center'; context.textBaseline = 'hanging'; context.strokeText(text, position.x, position.y); context.fillText(text, position.x, position.y); return canvas.toDataURL('image/png'); }; // 使用方式 <img src="https://xxx.xxx.jpg" /> <p className="warter-mark-area" style={{ backgroundImage: `url(${getBase64Background({})})` }} />
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('180px 120px'); 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=\'100%\' height=\'100%\' xmlns=\'http://www.w3.org/2000/svg\' version=\'1.1\'><text width=\'100%\' height=\'100%\' x=\'20\' y=\'68\' transform=\'rotate(-20)\' fill=\'rgba(0, 0, 0, 0.2)\' font-size=\'14\' stroke=\'rgba(255, 255, 255, .2)\' stroke-width=\'1\'>${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('px', '')) < 180) { setWaterMarkStyle(`${width} ${height.replace('px', '') / 2}px`); }; previousSibling.style.height = height; previousSibling.style.width = width; previousSibling.style.top = `${offsetTop}px`; previousSibling.style.left = `${offsetLeft}px`; // 加载 loading 隐藏 nextSibling.style.display = 'none'; }; 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> ); };
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
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!