使用Web?Component實(shí)現(xiàn)防篡改水印
這篇文章的關(guān)鍵可以分為3個(gè)部分,Web Component + 防篡改 + 水印生成。在使用Web Component之前,我已經(jīng)通過(guò)MutationObserver實(shí)現(xiàn)了防篡改水印的第一版。但在了解到Web Component的特性之后,我認(rèn)為也許用Web Component也不錯(cuò),因?yàn)?strong>Web Component內(nèi)部有鉤子天然支持被篡改時(shí)被觸發(fā),用來(lái)防篡改非常方便。下面也會(huì)對(duì)MutationObserver與Web Component的實(shí)現(xiàn)做比較。
設(shè)計(jì)目標(biāo)
設(shè)計(jì)一個(gè)hook用于插入水印至ref指定的組件中,被插入的水印節(jié)點(diǎn)應(yīng)當(dāng)不可篡改。
const { data: username } = useRequest(...) const ref = useWatermark(username); // 水印組件會(huì)插入ref.current對(duì)應(yīng)的DOM節(jié)點(diǎn) return <div ref={ref}> {children} </div>
水印生成原理
創(chuàng)建一個(gè)div節(jié)點(diǎn),將背景設(shè)置為一個(gè)透明的水印圖片,將z-index設(shè)置為10000疊加在站點(diǎn)上即可實(shí)現(xiàn)水印效果。
生成水印圖
水印圖可以在前端直接生成,可以使用canvas通過(guò)命令繪制,或預(yù)聲明svg字符串。我選用的是svg字符串生成,因?yàn)槭褂胹vg清晰度較高,也比較簡(jiǎn)單。將svgString定義好,再轉(zhuǎn)換成base64即可。
const svgString = `<svg xmlns="http://www.w3.org/2000/svg" width="400px" height="146px"> <text x="10px" y="73px" text-anchor="start" transform="rotate(-20 0 73)" fill="rgba(40, 47, 56, 0.03)" font-weight="500" font-size="14" font-family="Helvetica Neue,Helvetica,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,WenQuanYi Micro Hei,sans-serif" > ${content} </text> <text x="210px" y="146px" text-anchor="start" transform="rotate(-20 200 146)" fill="rgba(40, 47, 56, 0.03)" font-weight="500" font-size="14" font-family="Helvetica Neue,Helvetica,Arial,PingFang SC,Hiragino Sans GB,Microsoft YaHei,WenQuanYi Micro Hei,sans-serif" > ${content} </text> </svg>`; const background = 'data:image/svg+xml;base64,' + window.btoa(svgString);
CSS與DIV布局
注意所有CSS都應(yīng)該直接定義在div節(jié)點(diǎn)上,并且加上!important,這樣能有效避免樣式被覆蓋。
position: absolute !important; top: 0px !important; right: 0px !important; bottom: 0px !important; left: 0px !important; overflow: hidden !important; display: block !important; opacity: 1 !important; z-index: 10000 !important; pointer-events: none !important; // 可以防止鼠標(biāo)事件被水印節(jié)點(diǎn)攔截 background: url(${background});
const node = document.createElement('div'); watermarkRef.current = node; node.setAttribute( 'style', `position: absolute !important; top: 0px !important; right: 0px !important; bottom: 0px !important; left: 0px !important; overflow: hidden !important; display: block !important; opacity: 1 !important; z-index: 10000 !important; pointer-events: none !important; background: url(${background});` );
防篡改原理
MutationObserve
const observer = new MutationObserver(function (entries) { // 因?yàn)镸utationObserve沒辦法監(jiān)聽自己的屬性是否被修改,自己是否被移除,只能監(jiān)聽父組件 // 通過(guò)對(duì)父組件觀測(cè),entry.type = 'attributes'可以判斷水印節(jié)點(diǎn)的屬性是否被修改 // entry.type = 'childList' 可以判斷水印節(jié)點(diǎn)是否被移除 for (const entry of entries) { if ( (entry.type === 'attributes' && entry.target === watermarkRef.current) || (entry.type === 'childList' && Array.from(entry.removedNodes).includes(watermarkRef.current)) ) { removeWatermark(); generateWaterMark(); return; } } }); const config = { attributes: true, childList: true, subtree: true }; observer.observe( parentNode, // 水印掛載到的父組件 config );
Web Component
使用Web Component的好處就是可以直接綁定回調(diào)函數(shù),檢測(cè)自己是否被篡改或移除。
class WatermarkElement extends HTMLElement { static observedAttributes = ["style"]; // 需要觀測(cè)的屬性 constructor() { super(); } connectedCallback() { // 當(dāng)組件掛載至dom中,可以用來(lái)初始化 } disconnectedCallback() { // 當(dāng)組件從document中移除,用于檢測(cè)水印被刪除 } adoptedCallback() { // 當(dāng)組件在document中被移動(dòng) // 若觸發(fā)則表示水印被移動(dòng),可能失效 } attributeChangedCallback(name, oldValue, newValue) { // 若觸發(fā)表示style屬性被操作,可能是惡意篡改 } } customElements.define("watermark-element", MyCustomElement);
到此這篇關(guān)于使用Web Component實(shí)現(xiàn)防篡改水印的文章就介紹到這了,更多相關(guān)Web Component防篡改水印內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS實(shí)現(xiàn)仿蘋果底部任務(wù)欄菜單效果代碼
這篇文章主要介紹了JS實(shí)現(xiàn)仿蘋果底部任務(wù)欄菜單效果代碼,可實(shí)現(xiàn)鼠標(biāo)滑過(guò)顯示大圖標(biāo)功能,涉及javascript鼠標(biāo)事件及頁(yè)面元素遍歷并修改屬性的技巧,需要的朋友可以參考下2015-08-08js文件中引入另一個(gè)js文件的4種方法總結(jié)
JavaScript文件是一個(gè)文本類型的文件,在任何文本編輯器中都可以被打開和編輯,JavaScript文件的擴(kuò)展名為js,這篇文章主要給大家介紹了關(guān)于js文件中引入另一個(gè)js文件的4種方法總結(jié),需要的朋友可以參考下2023-12-12webpack結(jié)合express實(shí)現(xiàn)自動(dòng)刷新的方法
這篇文章主要給大家介紹了關(guān)于webpack結(jié)合express實(shí)現(xiàn)自動(dòng)刷新的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用webpack具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05javascript編程開發(fā)中取色器及封裝$函數(shù)用法示例
這篇文章主要介紹了javascript編程開發(fā)中取色器及封裝$函數(shù),結(jié)合實(shí)例形式分析了javascript封裝$函數(shù)及數(shù)值運(yùn)算、頁(yè)面元素動(dòng)態(tài)操作實(shí)現(xiàn)取色器功能相關(guān)技巧,需要的朋友可以參考下2017-08-08