c++ - 尝试使用 boost asio PUT 时出现 Amazon S3 403 错误

标签 c++ boost amazon-s3 boost-asio

我正在尝试使用带有 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 响应,并使用了以下请求 header

...

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.1\r\n";
req += "Host: mybucket.s3-us-west-1.amazonaws.com\r\n";
req += "Accept: */*\r\n";
req += "Content-Lenght: 4\r\n";
req += "Expect: 100-continue\r\n\r\n";

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++ 程序中硬编码一个请求通常是行不通的;您需要让您的应用程序生成一个签名才能使其长期工作。

关于c++ - 尝试使用 boost asio PUT 时出现 Amazon S3 403 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31797908/

相关文章:

c++ - 使用类型= smth。和模板化类型

c++ - 查找指向 NULL 的指针

c++ - std::regex 用于将由冒号分隔的字符串解析为不同的组

c++ - 三次贝塞尔曲线 : What to do when leading coefficient is zero?

amazon-web-services - 设置权限后,为什么我无法从 s3 存储桶下载文件?

c++ - 为什么这个 C++0x 程序会产生意外的输出?

c++ - boost图形库: named_graph and remove_vertex

c++ - 如何为 boost::units::si::angular_acceleration 赋值?

file - 如何将使用 Rusoto 从 S3 下载的文件保存到我的硬盘?

javascript - Amazon S3 上的 RequireJS 使用了错误的 URL