当前位置:网站首页>[web technology] 1348- talk about several ways to implement watermarking
[web technology] 1348- talk about several ways to implement watermarking
2022-06-12 22:20:00 【pingan8787】
Have a problem
On a daily basis , We often encounter a lot of sensitive data , To prevent data leakage , We need to do something on the data ” packing “. The purpose is to let those who deliberately leak data ” Lawbreakers “ Forced by serious ” Public opinion pressure “ And abandon the wrongdoing , Make it ” Attempted crime “, Achieve the effect of subduing soldiers without fighting . And we in the security department , The concept of data security has long been deeply rooted in the bone marrow , Every word , Each image , Pay attention to whether there is a risk of leakage , How to prevent data leakage , It's something we've been thinking about . For example, the watermark of the picture , It is a problem that we often involve in the process of work . Because its work content is the development of audit platform , Some risk pictures often appear on the audit platform , Considering the uneven safety awareness of auditors , So to prevent unsafe things from happening , It is necessary to add watermark to the picture .
To analyze problems
First , Considering the business scenario , The only problem at this stage is to worry about data leakage during the audit process , For the time being, we only consider explicit watermarking , Add some words or other data that can distinguish your personal identity on the picture . In this way, individuals can be traced according to the leaked data , Of course , Save against a rainy day , The warning function of prevention is the most important .
solve the problem
Realization way
There are many ways to implement watermark , According to the personnel division of functions, it can be divided into front-end watermark and back-end watermark , The advantages of front-end watermarking can be summarized into three points , First of all , It can not occupy server resources , Completely dependent on the computing power of the client , Reduce server pressure . second , Fast , No matter what kind of front-end implementation , The performance is better than the back-end . Third , The implementation is simple . The biggest advantages of implementing watermark on the back end can also be summarized as three points , It's security , Security , Security . You know , Microblogging is a back-end watermarking scheme . But on balance , We still use the front-end scheme to realize the watermark . The following will also briefly introduce nodejs How to implement back-end image watermarking .
node Realization
Provide three npm package , This part is not the focus of our article , Simple demo.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');
});Need to install GraphicsMagick perhaps ImageMagick;2,node-images:https://github.com/zhangyuanwei/node-images
var images = require("images");
images("input.jpg") //Load image from file
// Load the image file
.size(400) //Geometric scaling the image to 400 pixels width
// Scale the image proportionally to 400 Pixel width
.draw(images("logo.png"), 10, 10) //Drawn logo at coordinates (10,10)
// stay (10,10) Draw at Logo
.save("output.jpg", { //Save the image to a file, with the quality of 50
quality : 50 // Save picture to file , The picture quality is 50
});No other tools need to be installed , Lightweight ,zhangyuanwei Developed by Chinese people , Chinese document ;3,jimp:https://github.com/oliver-moran/jimp Collocation gifwrap Realization gif watermark ;
The front-end implementation
1, The background image realizes full screen watermark
You can view the effect on Alibaba's internal and external personal information pages , principle :

advantage : The picture is generated by the back end , Security ; shortcoming : Need to initiate http request , Get picture information ; Effect display : Because it's an internal system , Inconvenient to show the effect .
2,dom Realize full image watermark and image watermark
In the picture onload Get the width and height of the picture in the event , The watermark area is generated according to the image size , Cover the upper layer of the picture ,dom Copy or other information with watermark content , The implementation is relatively simple .
const wrap = document.querySelector('#ReactApp');
const { clientWidth, clientHeight } = wrap;
const waterHeight = 120;
const waterWidth = 180;
// Calculate the number of
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');
// Set the offset value dynamically
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 = ' Test watermark ';
wrap.appendChild(waterDom);
}
}advantage : Easy to implement ; shortcoming : Too large or too many pictures will have a performance impact ; Effect display :

3,canvas Realization way ( Implementation scheme of the first version ) Method 1 : Operate directly on the picture
I don't say much nonsense , Go straight to the code
useEffect(() => {
// gif Diagram does not support
if (src && src.includes('.gif')) {
setShowImg(true);
}
image.onload = function () {
try {
// Images that are too small do not load watermarks
if (image.width < 10) {
setIsDataError(true);
props.setIsDataError && props.setIsDataError(true);
return;
}
const canvas = canvasRef.current;
canvas.width = image.width;
canvas.height = image.height;
// Set watermark
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);
// Set watermark floating layer
const pattern = context.createPattern(innerCanvas, 'repeat');
context.fillStyle = pattern;
context.fill();
} catch (err) {
console.info(err);
setShowImg(true);
}
};
image.onerror = function () {
setShowImg(true);
};
}, [src]);advantage : Pure front-end implementation , The image copied by right clicking is also watermarked ; shortcoming : I won't support it gif, Pictures must support cross domain ; Effect display : The following gives .
Method 2 :canvas Generate watermark url Assign a value to css background attribute
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');
};
// Usage mode
<img src="https://xxx.xxx.jpg" />
<div className="warter-mark-area" style={
{ backgroundImage: `url(${getBase64Background({})})` }} />advantage : Pure front-end implementation , Support cross-domain , Support git Figure watermark ; shortcoming : Generated base64 url The larger ; Effect display : The following gives . In fact, according to these two canvas You can easily think of a third way , Is to cover a layer on the top of the picture Non pictorial in the first method canvas, This can perfectly avoid the shortcomings of the two schemes . But stop for a moment and think , A combination of the two options , Or use canvas To draw , Is there a simpler way to understand . Yes , use svg replace .
4,SVG The way ( The scheme in use ) Give a react Version of the watermark component .
export const WaterMark = (props) => {
// Get watermark data
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;
// Set the background and background styles
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;
// Get the width and height of the picture
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`;
// load loading hide
nextSibling.style.display = 'none';
};
const onError = (event) => {
setIsError(true);
};
return (
<div className={styles.water_mark_wrapper} ref={boxRef}>
<div className={styles.water_mark_box} style={boxStyle} />
{isError
? <ErrorSourceData src={src} showSrc={showSrc} height={propsHeight} text=" Picture loading error " helpText=" Click the copy picture link " />
: (
<>
<img onLoad={onLoad} referrerPolicy="no-referrer" onError={onError} src={src} alt=" Picture display error " />
<Icon className={styles.img_loading} type="loading" />
</>
)
}
</div>
);
};advantage : Support gif Figure watermark , There is no cross domain problem , Use repeat attribute , No insertion dom The process , Asexual problem ; shortcoming :...dom Structure display :

5, Renderings show canvas and svg The effect achieved is not very different in the display , So the effect picture shows all of them in one picture .

QA
Question 1 :
If you put watermark Of dom Deleted , The picture is watermark free ? answer : You can use MutationObserver monitor water The node of , If the node is modified , The picture is also hidden ;
Question two :
Right click to copy the picture ? answer : All pictures have the right-click function disabled
Question 3 :
If from the console network Get picture information ? answer : There is no good solution for this operation , The back-end implementation scheme is recommended
summary
The watermark scheme implemented by the front end is always a temporary scheme , The back-end implementation of the business consumes server resources , In fact, the most ideal solution is to provide an independent watermark service , Although there is a slight delay in the loading process , But relative to data security , Millisecond delay is acceptable , In this way, it can ensure that the service stability of the business will not be affected . In the daily Q & a process , There will also be many business parties coming to me to communicate the watermark blocking risk points , You can only reply to them with the importance of data security at a time , Of course , The size of the watermark , transparency , The intensity is also constantly being tuned , I believe there will be a version , It can not only play the role of watermark , It can also better solve the occlusion problem .
The author of this article :ES2049 / Bulu
Link to this article :https://segmentfault.com/a/1190000040425430
边栏推荐
- A puzzle about + =
- [Jianzhi offer simple] Jianzhi offer 06 Print linked list from end to end
- 打新债开户安全么,新手该怎么操作?
- Leetcode: the maximum number of building change requests that can be reached (if you see the amount of data, you should be mindless)
- QT quick 3D learning: use mouse and keyboard to control node position and direction
- The kotlin coroutine -- coroutine context and exception propagation
- Qt Quick 3D学习:鼠标拾取物体
- China's elastic belt market trend report, technical dynamic innovation and market forecast
- 【LeetCode】209. 长度最小的子数组
- [simple] 155 Minimum stack
猜你喜欢

Dolphin-2.0.3 cluster deployment document

最近公共祖先问题你真的学会了吗?

The interface testing tool apipos3.0 is applicable to process testing and reference parameter variables

Mysql case when then函数使用

Ansible foundation and common modules (I)

QT quick 3D learning: mouse picking up objects

Open source background management system suitable for outsourcing projects

Pat grade A - 1167 Cartesian tree (30 points) (buildtree + level traversal)

Qt Quick 3D学习:鼠标拾取物体

C # reading table data in word
随机推荐
Open source background management system suitable for outsourcing projects
[sword finger offer] sword finger offer 35 Replication of complex linked list
[C language] data type occupation
PE installation win10 system
【LeetCode】数组中第K大的元素
Is it safe to open an account in flush? How to open an account online to buy stocks
Ansible playbook和变量(二)
USB mechanical keyboard changed to Bluetooth Keyboard
[probability theory and mathematical statistics] final review: formula summary and simple examples (end)
flutter系列之:flutter中常用的GridView layout详解
Su embedded training day13 - file IO
Unity commonly used 3D mathematical calculation
Can tonghuashun open an account? Is it safe to open an account in tonghuashun? How to open a securities account
Is it safe to open an account with new bonds? How should novices operate?
Preliminary use of jvisualvm
Leetcode Yanghui triangle
Is it safe to open an account in tonghuashun? How to open an account
The kotlin coroutine -- coroutine context and exception propagation
JVM Basics - > What are the thread shared areas in the JVM
Role of volatile keyword