ReactJS: рендеринг частного имиджевого ресурса из S3 - PullRequest
0 голосов
/ 17 октября 2018

Я использую серверный серверный сервер NodeJS, который позволяет веб-интерфейсу (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_ID и AWS_SECRET_ACCESS_KEY.

ОднакоТеперь я хочу, чтобы иметь возможность визуализировать это изображение на ReactJS или React Native.Вы рекомендуете создать другой маршрут NodeJS, который называется что-то вроде /render, и каким-то образом передавать его на сервер?Если да, как я могу это сделать?

В качестве альтернативы, следует ли мне рендерить его непосредственно с внешнего интерфейса и рисковать, предоставляя пользователю ключи AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY?

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

После ряда проб и ошибок я обнаружил, что самым элегантным решением является обеспечение 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 конечному пользователю.

Во-вторых, если я хочу ограничить доступ к этому маршруту, я могу просто использовать passportJS внутри NodeJS, чтобы, например, ограничить доступ кактив только для зарегистрированных пользователей.Это полезно во многих сценариях, например, в случае требований GDPR.

0 голосов
/ 17 октября 2018

Решение простое:

  1. Произведите рандомизацию URL-адресов S3, чтобы их нельзя было угадать (например, используйте UUID)
  2. Сделайте эти ресурсы общедоступными
  3. Сделайте все S3частные папки, поэтому, если у пользователя в одном браузере есть URL-адрес для определенного ресурса, он / она не может перечислить содержимое папок S3 выше.

Таким образом, пользователи смогут получить доступ только к активам, которые выотправлять их с сервера + без ключей API AWS (отправка ключей в браузер - огромный недостаток безопасности)

Это та же самая концепция, например, Google Docs, Dropbox использует, когда вы делитесь ссылкой и отправляете ее кому-то.Все в мире смогут прочитать эту ссылку, но если ссылка не поддается предположению, доступ к ресурсу возможен только в том случае, если вы поделитесь этой ссылкой.

...