ReactJS:从S3渲染私有图像资产

时间:2018-10-17 08:26:41

标签: node.js reactjs amazon-web-services react-native amazon-s3

我正在使用NodeJS后端API服务器,该服务器允许前端(ReactJS / React Native)使用表单数据上载图像。这是我正在使用的代码:

const s3 = new aws.S3({
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: "us-east-1",
});

...

const upload = multer({
  storage: multerS3({
    s3,
    bucket: process.env.AWS_BUCKET,
    acl: 'private',
    metadata(req, file, cb) {
      cb(null, {fieldName: file.fieldname});
    },
    key(req, file, cb) {
      cb(null, Date.now().toString() + '.png');
    }
  })
})

...

app.post('/upload', upload.single('photo'), (req, res, next) => {
  res.json(req.file)
})

API服务器正常工作,并且使用AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY将图像上传到私有安全存储区中。

但是现在我希望能够在ReactJS或React Native上渲染该图像。您是否建议构建另一个名为/render之类的NodeJS路由,然后以某种方式将其流式传输到后端?如果是,我该怎么办?

或者,我是否应该直接从前端渲染它,并冒着将AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY密钥暴露给用户的风险?

3 个答案:

答案 0 :(得分:1)

解决方案很简单:

  1. 随机化S3 URL,以使它们不可猜测(例如,使用UUID)
  2. 公开这些资产
  3. 将所有S3文件夹设为私有,这样,如果一个浏览器中的用户具有指向某些资产的URL,则他/她将无法在上面列出S3文件夹的内容。

这样,用户将只能访问您从服务器+向他们发送的资产,而无需AWS API密钥(将密钥发送到浏览器将是巨大的安全漏洞)

这是非常相同的概念,例如Google Docs,Dropbox在共享链接并将其发送给他人时使用。世界上的每个人都可以阅读该链接,但是如果链接不可猜测,则只有共享该链接,才能访问资产。

答案 1 :(得分:1)

经过多次试验和错误,我发现最优雅的解决方案是让NodeJS负责与S3的通信。然后,前端将通过以下路线GET来自NodeJS的图像:

  app.get("/image/:imageId", function(req, res, next) {
    var params = { Bucket: keys.AWS_BUCKET, Key: req.params.imageId };
    s3.getObject(params, function(err, data) {
      if (err) {
        return res.send({ error: err });
      }
      res.send(data.Body);
    });
  });

为什么我认为这比 luboskmac 提出的解决方案更为优雅?

对于初学者来说,我不会在任何时候向公众公开该资产。我只是向最终用户透露NodeJS GET路由。

第二,如果我想限制对该路由的访问,则可以简单地在NodeJS中使用passportJS,例如,将对资产的访问限制为仅登录的用户。这在许多情况下都很有用,例如GDPR要求。

答案 2 :(得分:0)

出于隐私和安全考虑,不建议公开存储桶,请改用 Amplify

相关问题