6

有很多关于 node 文件上传的文章、教程和问题,但它们大多是为初学者准备的,没有一个完全解释了如何保护生产环境中的文件上传。我一直在努力寻找如何做到这一点的完整答案,但没有成功。

下面是对我的发现的解释。

  1. 限制上传文件大小:

    app.use(express.limit('4mb'));
    
  2. 将文件上传限制为仅某些路线:我无法使其实际工作,但这是我尝试过的:

    代替:

    app.use(express.bodyParser());
    

    app.use(express.json());
    app.use(express.urlencoded());
    

    并将多部分中间件添加到每个上传路由:

    app.post('/upload', express.multipart(), uploadController.uploadPhoto);
    

    这部分不起作用,但如果我离开,上传工作正常express.bodyParser()。那么我做错了什么?

  3. 在将上传保存到磁盘之前检查上传的文件类型:

    我无法弄清楚这部分,但一个建议是编写一个自定义中间件,该中间件使用强大的解析文件上传并尝试在保存文件之前调整文件大小(假设它是一个图像),使用像图像魔术这样的库。建议是这样可以使图像安全并确保它实际上是图像(因为如果不是图像,该过程将失败)。

    但这仅适用于图像,因此它不是一个完整的解决方案。

    我该如何实施?任何示例代码?

为了确保上传安全,我还有什么遗漏吗?

4

2 回答 2

2

方法 2 确实有效。我遇到的问题是

app.use(passport.session());

正在阻止它工作。因此,如果您passport.js用于身份验证,这可能是问题所在。如果您使用这种方法,请确保在实际路线上添加安全性。


我最终使用了这个插件

https://github.com/tih-ra/alleup

它非常适合图像上传,并自动将文件调整为多个版本并将它们上传到亚马逊 s3。使用此插件将与使用方法 3 内联,但tmp文件先上传到文件夹,然后再删除。

于 2013-01-23T12:12:24.517 回答
1

我正在使用多方上传(和流式传输)文件。

var form = new multiparty.Form();

到 1:

form.on('progress', function (bytesReceived) {
  if (262144000 < bytesReceived) {
   abortConnection('filesizeexeeded');
  }
});

实现自己的中止连接功能;例如:

function abortConnection(reason) {
  res.writeHead(413, { 'Connection': 'close' });
  return res.end(reason);
}

警告:浏览器很可能会重试上传(最多 4 次)。我正在使用 websocket 连接来取消客户端的上传。

To 2:(使用多方)

To 3:我创建了一个要点,展示了如何使用mmmagic即时检查 mime 类型。

如果您将护照与多方结合使用,您可能会发现这很有用:

https://github.com/jaredhanson/passport/pull/106#issuecomment-14188999

于 2014-01-20T14:35:42.383 回答