我一直在用这种方式让人们在画布上绘制内容并将其上传到服务器。 它工作正常,除了人们能够插入自己的图像(我的朋友测试它)
以下是它的作用:
人点击“提交”他们的画布保存到base64并使用$ .post()发送
$ .post()中的php文件运行并将文件保存到服务器中的文件
有没有办法阻止用户提交自己的图片,我已经检查过图片尺寸等等,但他们只是调整尺寸并提交。 (我认为由于我的小型服务器,php绘制图像的能力不会起作用)
答案 0 :(得分:1)
是否有任何阻止用户提交自己图片的方法
不。
任何人都可以通过完全绕过客户端代码来上传他们想要的任何内容。除了hacky启发式之外,你无能为力。 (他们已经在页面上了一段时间吗?是否检测到鼠标移动或屏幕触摸?他们真的画了什么东西吗?)这些东西也可以伪造,这只是一个头发更麻烦的黑客。不要为此烦恼,你会为自己创造更多的问题,而不是你要解决的问题。
答案 1 :(得分:1)
根据我的理解,如果你的应用程序是一个简单的绘图工具,那么一种简单的方法就是只发送一个包含所有用户手势的JSON,而不是保存图像本身。
这样,即使一个人仍然可以绕过你的应用程序,并且无法控制(即以编程方式)生成图像,他们也无法在服务器上保存例如图像。
这还允许您在保存之前对数据结构服务器端执行完整性检查,并在您的应用中实现cancel
功能。
然而,一个反作用的结果是随后增加的数据以节省大型图纸(但减少了较小的图纸)。
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>
答案 2 :(得分:0)
您可以检查图像数据,例如图像高度,宽度,甚至图像大小和颜色,具体取决于画布中呈现的内容。举个例子,假设画布是250 x 250像素,它只使用蓝色,红色和绿色的颜色渲染2D正方形。如果有三种以上的颜色,如果颜色不仅是蓝色,红色和绿色,或者如果画布不是250 x 250,则拒绝它。您还可以检查用户代理中的“referrer”值,但这可以轻松更改。