如何使用Express安全地上传Node中的文件?

时间:2013-01-22 14:09:37

标签: node.js file-upload express formidable

在节点中有很多关于文件上传的文章,教程和问题,但大多数是针对初学者的,没有一个完整地解释了如何保护文件上传以进行生产。 我已经非常努力地找到关于如何做到这一点的完整答案,但它没有成功。

以下是对我的调查结果的解释。

  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 个答案:

答案 0 :(得分:2)

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

app.use(passport.session());

阻止它工作。因此,如果您使用 passport.js 进行身份验证,则可能会出现问题。如果您使用此方法,请确保在实际路线上添加安全性。


我最终使用了这个插件

  

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

适用于图片上传,并自动将文件大小调整为多个版本并将其上传到亚马逊s3。使用此插件将与使用方法3一致,但文件首先上传到tmp文件夹,然后删除。

答案 1 :(得分:1)

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

var form = new multiparty.Form();

至1:

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

实现自己的中止连接功能; e.g:

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

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

至2 :(使用多方)

至3:我创建了一个gist,其中显示了如何使用mmmagic动态检查mime类型。

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

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