Amazon S3在尝试使用boost asio进行PUT时出现403错误

Amazon S3 403 error when attempting to PUT with boost asio

本文关键字:PUT 进行 错误 asio boost S3 Amazon      更新时间:2023-10-16

我正在尝试使用boost asio的PUT动词将文件上传到我的S3桶。

我用aws-sdk ruby gem生成了一个预签名的URL:

my_url = Aws::S3::Resource.new.bucket("mybucket").object("file.txt").presigned_url(:put)   
# my_url returns: https://mybucket.s3-us-west-1.amazonaws.com/file.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=MY_ACCESS_KEY_ID%2F20150803%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20150803T194921Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=a11bdaefc1c4580c0c21bfa889c75e4506de76a59e2e7eeaf7c35e9054daf15f

为了测试这个预签名URL,我使用curl上传一个文件(在SO中找到这个命令)

$ curl -v --upload-file file.txt "[URL_FROM_RUBY_CODE]"

返回200 OK响应,并使用以下请求头

...
PUT /file.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=MY_ACCESS_KEY_ID%2F20150803%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20150803T194921Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=a11bdaefc1c4580c0c21bfa889c75e4506de76a59e2e7eeaf7c35e9054daf15f HTTP/1.1
User-Agent: curl/7.30.0
Host: mybucket.s3-us-west-1.amazonaws.com
Accept: */*
Content-Length: 20
Expect: 100-continue
...
HTTP/1.1 200 OK
...

这个curl命令工作得很好,文件上传了。但是当我尝试使用boost asio时,我一直得到403 Forbidden错误。下面是我的c++代码:

boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(boost::asio::ip::tcp::resolver::query("mybucket.s3-us-west-1.amazonaws.com", "80"));
boost::asio::ip::tcp::socket sock(io_service);
boost::asio::connect(sock, iter);
std::string req = "PUT /file.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=MY_ACCESS_KEY_ID%2F20150803%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20150803T194921Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=a11bdaefc1c4580c0c21bfa889c75e4506de76a59e2e7eeaf7c35e9054daf15f HTTP/1.1rn";
req += "Host: mybucket.s3-us-west-1.amazonaws.comrn";
req += "Accept: */*rn";
req += "Content-Lenght: 4rn";
req += "Expect: 100-continuernrn";
req += "TEST";
boost::asio::write(sock, boost::asio::buffer(req.c_str(), req.length()));
char res[2048];
boost::asio::read(sock, boost::asio::buffer(res));

我只是不明白我在c++代码中做错了什么。有人能帮帮忙吗?

编辑这是我得到的回应。

HTTP/1.1 403 Forbidden
x-amz-request-id: 1BF06BB2183CF427
x-amz-id-2: JEzslTC9jsKbo2LiUV80rZhaSQpMkWjAcfqztXeR9lTsMrqt/cCPjJwWx/SphfQzqhutaZSq5d0=
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Mon, 03 Aug 2015 23:44:03 GMT
Connection: close
Server: AmazonS3

8de
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>AKIAIDKQLZIT2IIG33SQ</AWSAccessKeyId><StringToSign>AWS4-HMAC-SHA256
20150803T234253Z
20150803/us-west-1/s3/aws4_request
f962380b7de26fa6a92c84ea48cde101dcf38c653d01bb03105b8bc45b28fca9</StringToSign><SignatureProvided>6ce83e89e9b2c3322bad92fad584f9cb419273a307930cbce64954093424ddb9</SignatureProvided><StringToSignBytes>41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 0a 32 30 31 35 30 38 30 33 54 32 33 34 32 35 33 5a 0a 32 30 31 35 30 38 30 33 2f 75 73 2d 77 65 73 74 2d 31 2f 73 33 2f 61 77 73 34 5f 72 65 71 75 65 73 74 0a 66 39 36 32 33 38 30 62 37 64 65 32 36 66 61 36 61 39 32 63 38 34 65 61 34 38 63 64 65 31 30 31 64 63 66 33 38 63 36 35 33 64 30 31 62 62 30 33 31 30 35 62 38 62 63 34 35 62 32 38 66 63 61 39</StringToSignBytes><CanonicalRequest>PUT
/file.txt
X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;X-Amz-Credential=MY_ACCESS_KEY_ID%2F20150803%2Fus-west-1%2Fs3%2Faws4_request&amp;X-Amz-Date=20150803T234253Z&amp;X-Amz-Expires=900&amp;X-Amz-SignedHeaders=host
host:mybucket.s3-us-west-1.amazonaws.com
host
UNSIGNED-PAYLOAD</CanonicalRequest><CanonicalRequestBytes>50 55 54 0a 2f 66 69 6c 65 2e 74 78 74 0a 58 2d 41 6d 7a 2d 41 6c 67 6f 72 69 74 68 6d 3d 41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 26 58 2d 41 6d 7a 2d 43 72 65 64 65 6e 74 69 61 6c 3d 41 4b 49 41 49 44 4b 51 4c 5a 49 54 32 49 49 47 33 33 53 51 25 32 46 32 30 31 35 30 38 30 33 25 32 46 75 73 2d 77 65 73 74 2d 31 25 32 46 73 33 25 32 46 61 77 73 34 5f 72 65 71 75 65 73 74 26 58 2d 41 6d 7a 2d 44 61 74 65 3d 32 30 31 35 30 38 30 33 54 32 33ÌÌÌÌÌÌÌÌøèP

至少有一件事是非常明显的错误:你把"Content-Length"拼成了"Content-Lenght"。

更一般地说,请求签名是时间相关的;这个将在X-Amz-Date中指定的日期后15分钟(900秒)过期-即今天格林尼治标准时间20:05左右。如果在此时间之后运行应用程序,签名将过期,因此请求将被拒绝。在c++程序中硬编码请求通常是行不通的;您需要让您的应用程序生成签名以使其长期工作。