【问题标题】:SignatureDoesNotMatch: rejecting SignedURLSignatureDoesNotMatch:拒绝 SignedURL
【发布时间】:2020-06-27 05:10:15
【问题描述】:

我对使用 AWS S3 很陌生,我正在尝试将图像上传到 S3,但遇到了臭名昭著的 SignatureDoesNotMatch 错误。我确定了任何拼写错误:(即我的键中的前导、尾随空格),检查我的系统时间是否关闭,但都无济于事。我的工作流程如下(如果您想参考,主要取自教程:https://medium.com/@diego.f.rodriguezh/direct-image-upload-to-aws-s3-with-react-and-express-2f063bc15430)。我尝试关注之前关于此问题的所有帖子,但仍然无法解决。

首先,我在 query.js 中处理 URL 的签名:

 accessKeyId: process.env.S3_KEY, // 存储在.env文件中
    secretAccessKey: process.env.S3_SECRET, // 存储在 .env 文件中
    region: process.env.BUCKET_REGION // 这是指您的存储桶配置。
  });
// 创建一个 S3 实例
常量 s3 = 新 AWS.S3();

// 从 env 变量中检索存储桶名称
const Bucket = process.env.BUCKET_NAME;
// PUT URL 生成器
函数 generatePutUrl(Key, ContentType) {
  
  返回新的承诺((解决,拒绝)=> {
    // 注意 Bucket 是从上面的 env 变量中检索的。
    console.log('关键是:', Key)
    const params = { Bucket, ContentType, Expires:3600, Key };
        // 注意本例中的操作是putObject
    s3.getSignedUrl('putObject', params, function(err, url) {
      如果(错误){
        控制台日志(错误)
        拒绝(错误);
      }
      // 如果没有错误,我们可以发回预签名的 PUT URL
      解决(网址);
    });
  });
}

然后在 index.js 中:


// PUT URL
app.get('/generate-put-url', (req,res)=>{
  // Both Key and ContentType are defined in the client side.
  // Key refers to the remote name of the file.
  // ContentType refers to the MIME content type, in this case image/jpeg
  const { Key, ContentType } =  req.query;
  
  generatePutUrl(Key, ContentType).then(putURL => {
    console.log({putURL})
    res.send({putURL});
  })
  .catch(err => {
    res.send(err);
  });
});

app.listen(port, () => {
  console.log(`Listening on port ${port}`);
});

然后是我的组件 uploader.js,它真正呈现了上传按钮,我在其中对签名的 url 发出 get 请求,然后我返回它以向 S3 发出 put 请求:

getImage = e => {
    const files = e.target.files;
    if (files && files.length > 0) {
      const file = files[0];
      this.setState({ file });
    }
  };

  uploadFile = e => {
    
    e.preventDefault();
    const { file } = this.state;
    this.setState({message:'Uploading...'})
    const contentType = file.type; // eg. image/jpeg or image/svg+xml
    console.log(contentType)
    const generatePutUrl = 'http://localhost:4000/generate-put-url';
    const options = {
      params: {
        Key: file.name,
        ContentType: contentType,
      },
      headers: {
        'Content-Type': contentType
      }
    };
    
    axios.get(generatePutUrl, options).then(res => {
      const {
        data: { putURL }
      } = res;
      
      axios
        .put(putURL, file, options)
        .then(res => {
            
          this.setState({message:'Upload Successful'})
          setTimeout(()=>{
            this.setState({message:''});
            document.querySelector('#upload-image').value='';
          }, 2000)
        })
        .catch(err => {
          this.setState({message:'Sorry, something went wrong'})
          console.log('err', err);
        });
    });
  };

作为参考,我在我的签名 URL 进入 put 请求之前记录了它,它看起来像这样(访问密钥 x-ed)

putURL: 'https://polici-media.s3.us-east-2.amazonaws.com/32bitadder.JPG?Content-Type=image%2Fjpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIXXXXXXXXXXX%2F20200627%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20200627T050401Z&X-Amz-Expires=3600&X-Amz-Signature=d12f6228e20d3bc5fab2b38bd6e250992f3e362418eb8f61ed6c886a71eb46e7&X-Amz-SignedHeaders=host'

对于那些可能在本教程中跟随的人,我真正改变的只是从使用端口 3500 到端口 4000 作为我的后端,但在这种情况下这不是问题。我也将此 URL 放在邮递员中无济于事,尽管具有正确标头和身份验证的 URL https://polici-media.s3.us-east-2.amazonaws.com/32bitadder.JPG 在邮递员上工作得很好

【问题讨论】:

  • 这能回答你的问题吗? Pre-Signed S3 URL Signature Does Not Match
  • 不是真的,因为我包含了所有标题(请参阅我上面的代码)。我之前也看过这个
  • 您为什么要以您现在的方式将变量options 用于多种用途?这似乎有问题。
  • 我同意这不是很好,但在这种情况下,我看不出它会如何导致任何问题。我什至为每个变量分配了不同的变量,这是同一个问题。

标签: node.js amazon-web-services amazon-s3 aws-sdk-js


【解决方案1】:

我通过从标题中删除 Content-Type 解决了这个问题。

【讨论】:

    猜你喜欢
    • 2017-09-29
    • 2018-06-21
    • 2012-04-14
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    • 2017-08-08
    • 2012-08-25
    • 2021-09-07
    相关资源
    最近更新 更多