PUT в S3 с предварительно подписанным URL-адресом дает ошибку 403

Я использую Node, чтобы получить заранее подписанное RUL для S3, чтобы ПОСТАВИТЬ изображение в корзину S3.

var aws = require('aws-sdk');
// Request presigned URL from S3
exports.S3presignedURL = function (req, res) {
  var s3 = new aws.S3();
  var params = {
    Bucket: process.env.S3_BUCKET, 
    Key: '123456', //TODO: creat unique S3 key
    //ACL:'public-read',
    ContentType: req.body['Content-Type'], //'image/jpg'
  };
  s3.getSignedUrl('putObject', params, function(err, url) {
      if(err) console.log(err);
      res.json({url: url});
  });
};

Это успешно извлекает заранее подписанный URL-адрес формы ...

Вернувшись на клиентскую сторону (веб-приложение), я использую angular для создания HTTP-запроса. Я использовал и $ http, и ngFileUpload, но безуспешно. Вот мой код ngFileUpload.

Upload.upload({
    url: responce.data.url, //S3 upload url including bucket name
    method: 'PUT',
    'Content-Type': file.type, //I have tried putting the ContentTyep header all over
    headers: { 
        //'x-amz-acl':'public-read',
        'Content-Type': file.type, 
    }, 
    data: { 
        file: file,
        headers:{'Content-Type': file.type,}
    },                         
})

Однако, похоже, независимо от того, как я форматирую свой заголовок, я всегда получаю ошибку 403. В XML-коде ошибки говорится:

SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.

Я не думаю, что CORS - это проблема. Первоначально я получал некоторые ошибки CORS, но они выглядели иначе, и я заставил их уйти с некоторыми изменениями в настройках CORS ведра S3. Я пробовал много проб и ошибок, устанавливая заголовки как для запроса presignedURL, так и для запроса PUT к S3, но я не могу найти правильную комбинацию.

Я заметил, что когда я console.log ошибка ответа 403, поле

config.headers:{Content-Type: undefined, __setXHR_: ƒ, Accept: "application/json, text/plain, */*"}

Это говорит о том, что заголовок Content-Type не установлен? Как такое может быть, если я установил этот заголовок везде, где только могу подумать? В любом случае, я уже немного бился головой об стену ...


РЕДАКТИРОВАТЬ: по запросу мой Current CORS. (Я бросил все, чтобы избавиться от предупреждений CORS, которые у меня были ранее. Я сокращу их до самого необходимого только после того, как мои загрузки заработают.)

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedOrigin>http://localhost:9500</AllowedOrigin>
    <AllowedOrigin>https://localhost:9500</AllowedOrigin>
    <AllowedOrigin>http://www.example.com</AllowedOrigin>
    <AllowedOrigin>https://www.example.com</AllowedOrigin>
    <AllowedOrigin>http://lvh.me:9500</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <ExposeHeader>ETag</ExposeHeader>
    <AllowedHeader>*</AllowedHeader>
    <AllowedHeader>Content-Type</AllowedHeader>
    <AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>

person honkskillet    schedule 27.01.2018    source источник
comment
Вам нужно больше журналов отладки. Зарегистрируйте, например, значение file.type.   -  person Michael - sqlbot    schedule 28.01.2018
comment
@ Michael-sqlbot Да, я все зарегистрировал, но для краткости я удалил их. file.type журналы images / png   -  person honkskillet    schedule 29.01.2018
comment
Показать текущую конфигурацию CORS корзины?   -  person Michael - sqlbot    schedule 29.01.2018
comment
Я получаю аналогичную ошибку. Вы поняли?   -  person Evan    schedule 21.03.2018
comment
Я не. Пожалуйста, дайте мне знать, если вы это сделаете.   -  person honkskillet    schedule 21.03.2018
comment
У меня была такая же проблема, и я исправил ее, добавив localhost в конфигурацию CORS. docs.aws.amazon.com/AmazonS3/latest/dev/cors. html   -  person Bodhidharma    schedule 04.10.2019


Ответы (2)


Столкнулся с той же проблемой. Выяснилось, что тип содержимого, который я использовал для создания предварительно подписанного URL-адреса, не соответствует типу содержимого объекта, который я отправлял на S3. Я бы посоветовал вам добавить заголовок Expiration при создании предварительно подписанного URL-адреса (я тоже) и проверить в консоли, какой именно тип контента отправляется, когда вы выполняете ввод в S3. Кроме того, данные просто должны быть файлом, а не структурой, которую вы там создали.

person Adheer Araokar    schedule 23.10.2018
comment
Спасибо. Была такая же проблема с типом содержимого. - person Dan; 17.11.2018
comment
Спасибо! Ты спас мне жизнь. - person llxxff; 11.12.2019

У меня было 403 ошибки с несоответствием подписи, и я не мог понять, почему. Читая некоторые другие примеры, один из них сказал, что он должен быть запущен в us-east-1, потому что он не поддерживается в других регионах. Я был в us-east-2, переключился и работал точно такой же код.

Попробуйте использовать us-east-1

person Captnwalker1    schedule 17.02.2021