【问题标题】:Prevent users from submitting their own image with ajax?防止用户用ajax提交自己的图片?
【发布时间】:2017-09-27 20:27:06
【问题描述】:

我一直在努力让人们在画布上绘制东西并将其上传到服务器。 除了人们能够插入自己的图像外,它工作正常(我的朋友测试过)

它的作用如下:

  1. 用户点击“提交”他们的画布被保存到 base64 并使用 $.post() 发送

  2. $.post() 中的 php 文件运行并将文件保存到服务器中的文件中

有什么办法可以阻止用户提交自己的图片,我已经检查了图片尺寸等等,但他们只是调整大小并提交。 (由于我的服务器很小,我认为 php 绘制图像矩形的能力不会起作用)

【问题讨论】:

    标签: javascript php html canvas server


    【解决方案1】:

    有什么办法可以阻止用户提交自己的图片

    没有。

    任何人都可以通过完全绕过您的客户端代码来上传他们想要的任何内容。除了骇人听闻的启发式方法之外,您无能为力。 (他们在页面上已经有一段时间了吗?是否检测到鼠标移动或屏幕触摸?他们真的画了一些东西吗?)这些东西也可以伪造,只是更麻烦。不要为此烦恼,你会给自己制造的问题比你解决的要多。

    【讨论】:

    • 猜猜我只需要处理它。韦尔普。
    【解决方案2】:

    如果按照我的理解,您的应用是一个简单的绘图工具,那么一种简单的方法是只发送一个包含所有用户手势的 JSON,而不是保存图像本身。

    这样,即使仍然可以绕过您的应用程序并生成您无法控制的图像(即以编程方式),他们也无法在您的服务器上保存例如 pr0n 图像。

    这还允许您在保存数据结构服务器端之前对其进行完整性检查,并在您的应用中实现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>

    【讨论】:

    • 在我看来,这是一个比被接受的答案更好的答案。它还说明了解决一整类仿冒问题,例如用其他图像代替自己的作品。因为根据定义,图像 是完成作品的快照,而自己的作品包含一个维度,即随着时间的推移创建的过程。应该提交的正是这些数据,如有必要,服务器会将图像存储为缓存。
    【解决方案3】:

    您可以根据画布中呈现的内容检查图像数据,例如图像高度、宽度,甚至可能是图像大小和颜色。例如,假设画布是 250 x 250 像素,它仅使用蓝色、红色和绿色来渲染 2D 正方形。如果有超过三种颜色,如果颜色不仅是蓝色、红色和绿色,或者如果画布不是 250 x 250,则拒绝它。您还可以检查用户代理中的“推荐人”值,但这可以很容易地更改。

    【讨论】:

      猜你喜欢
      • 2015-12-20
      • 2017-01-19
      • 1970-01-01
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-19
      • 1970-01-01
      相关资源
      最近更新 更多