【问题标题】:S3 Upload image with pre-signed url from browserS3 从浏览器上传带有预签名 URL 的图像
【发布时间】:2016-09-16 16:46:32
【问题描述】:

我正在尝试将数据从浏览器上传到 s3 存储桶。我已经生成了一个预签名的 url,但我得到了 403 禁止响应。

我的服务器代码是

const s3 = new AWS.S3({
  accessKeyId: settings.resourceBucketKey,
  secretAccessKey: settings.resourceBucketSecret,
  region: 'eu-west-1'
})

const params = {
  Bucket: 'my-bucket',
  Key: 'photo.png',
  ContentType: 'image/png',
  ACL: 'authenticated-read',
}

const url = s3.getSignedUrl('putObject', params)

console.log(url)

我的客户端代码是(使用生成的 url)

const input = $('#myinput')

      input.on('change', (res) => {
        var theFormFile = $('#myinput').get()[0].files[0];

        $.ajax({
          url: url,
          type: 'PUT',
          contentType: 'image/png',
          processData: false,
          data: theFormFile,
        }).success(function(){
          alert('success')
        })
      }, false)

我已经在桶上设置了 cors 来:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

但我仍然得到 403 禁止响应。我要上传的图像称为“photo.png”。我在这里遗漏了什么吗?

【问题讨论】:

    标签: javascript amazon-s3


    【解决方案1】:

    预签名 URL 的创建者(您)必须具有访问 S3 存储桶以上传文件的权限。这在 S3 documentation 中有更雄辩的描述:

    预签名 URL 可让您访问 URL 中标识的对象, 前提是预签名 URL 的创建者有权 访问该对象。也就是说,如果您收到要上传的预签名 URL 一个对象,您只能上传该对象的创建者 预签名 URL 具有上传该对象所需的权限。

    确保创建预签名 URL 的 IAM 用户具有必要的权限。

    【讨论】:

    • 谢谢,这正是问题所在!
    • 如果它可以帮助其他流浪者。当通过调用Lambda 函数完成同样的操作时,该函数要么应该使用IAM Role 调用,即write & read 访问S3,或者它必须包含对 S3 具有读写访问权限的 IAM 用户的访问密钥。您在创建 Lambda 函数时选择的自动生成角色可能不需要访问 S3。
    【解决方案2】:

    从浏览器获取签名 url 的完整实现 - 享受吧!

    <body>
      <img height="200" width="200">
      <script>
    
        var mimes = {
            'jpeg': 'data:image/jpeg;base64,'
        };
    
          AWS.config.update({
              signatureVersion: 'v4',
              region: 'us-east-1',
              accessKeyId: '',
              secretAccessKey: ''
          });
    
          var bucket = new AWS.S3({params: {Bucket: 'xxxx'}});
    
          function encode(data)
          {
              var str = data.reduce(function(a,b){ return a+String.fromCharCode(b) },'');
              return btoa(str).replace(/.{76}(?=.)/g,'$&\n');
          }
    
          function getUrlByFileName(fileName,mimeType) {
              return new Promise(
                  function (resolve, reject) {
                      bucket.getObject({Key: fileName}, function (err, file) {
                          var result =  mimeType + encode(file.Body);
                          resolve(result)
                      });
                  }
              );
          }
    
          function openInNewTab(url) {
              var redirectWindow = window.open(url, '_blank');
              redirectWindow.location;
          }
    
          getUrlByFileName('sprites.png', mimes.jpeg).then(function(data) {
              //openInNewTab(data);
              document.querySelector('img').src = data;
          });
    
      </script>
    </body>
    

    【讨论】:

    • 别忘了加上 -
    • 我认为将您的 secretAccessKey 放入客户端代码不是一个好主意
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2019-12-05
    • 2018-07-10
    • 2019-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多