问题
I've been working on this way for people to draw stuff on canvas and upload it to the server. It works fine except for people being able to insert their own images (my friend tested it)
Here's what it does:
Person clicks "submit" their canvas is saved into base64 and is sent using $.post()
php file in the $.post() runs and saves the file to a file in the server
Is there any way from preventing the user to be able to submit their own images, I already check image dimensions and so on but they'd just resize it and submit it. (I don't think php's ability to draw image rects would work due to my small servers)
回答1:
Is there any way from preventing the user to be able to submit their own images
Nope.
Anyone can upload whatever they want by completely bypassing your client-side code. There's nothing you can do about this, outside of hacky heuristics. (Have they been on the page awhile? Were mouse movements or screen touches detected? Did they actually draw something?) These sorts of things can also be faked, it's just a hair more hassle to hack around. Don't bother with this, you'll create more problems for yourself than you will solve.
回答2:
If, as I understand it, your app is an simple drawing tool, then one easy way would be to only send a JSON containing all the user gestures, instead of saving the image per se.
This way, even if one could still bypass your app, and produce images out of you control (i.e programmatically), they wouldn't be able to save e.g pr0n images on your server.
This would also allow you to perform a sanity check of the data structure server side, before saving it, and to implement an cancel
feature in your app.
One counter-side effect however, would be a consequent increase of data to save on large drawings (but a decrease on smaller ones).
const ctx = canvas.getContext('2d');
let drawing = false,
rect = canvas.getBoundingClientRect(),
paths = [];
let savedData = '[]';
save_btn.onclick = _ => {
savedData = JSON.stringify(paths);
console.clear();
console.log(savedData);
// here send this JSON data to the server
};
load_btn.onclick = _ => {
// easy to grab from server too
paths = JSON.parse(savedData);
draw();
};
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// at each draw, we loop over all our paths
paths.forEach(p => {
ctx.lineWidth = p.strokeWidth;
ctx.strokeStyle = p.color;
ctx.beginPath();
const l = p.list;
ctx.moveTo(l[0], l[1]);
for (let i = 2; i < l.length; i += 2) {
ctx.lineTo(l[i], l[i + 1]);
}
ctx.stroke();
});
}
// returns a new path object
function makePath() {
return {
color: randCol(),
list: [],
strokeWidth: (Math.random() * 10) + 1
};
}
canvas.onmouseup = canvas.onmouseleave = e => {
drawing = false;
};
canvas.onmousedown = e => {
paths.push(makePath());
drawing = true;
}
canvas.onmousemove = throttle(e => {
if (!drawing) return;
// to minimize the size of our JSON data
// we fix the coordinates to precision(2)
let x = ~~((e.clientX - rect.left) *10)/10;
let y = ~~((e.clientY - rect.top) *10)/10;
paths[paths.length - 1].list.push(x, y);
draw();
});
window.onresize = window.onscroll = throttle(e => rect = canvas.getBoundingClientRect());
function throttle(callback) {
let active = false;
let evt;
const handler = function() {
active = false;
callback(evt);
}
return function handleEvent(e) {
evt = e;
if (!active) {
active = true;
requestAnimationFrame(handler);
};
};
}
function randCol() {
const letters = '0123456789ABCDEF'.split('');
let color = '#';
for (let i = 0; i < 6; i++) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
canvas{
border: 1px solid;
}
<button id="save_btn">save</button>
<button id="load_btn">load last saved</button><br>
<canvas id="canvas"></canvas>
回答3:
You can check image data such as the image height ,width, possibly even image size and color depending on what is rendered in the canvas. For an example let's say the canvas is 250 x 250 pixels and it renders 2D squares only using the colors blue, red, and green. If there are more than three colors, if the colors are not only blue, red, and green, or if the canvas is not 250 x 250 you deny it. You could also check the "referrer" value in the user agent, this can be easily changed though.
来源:https://stackoverflow.com/questions/43701886/prevent-users-from-submitting-their-own-image-with-ajax