【发布时间】:2015-02-12 16:59:53
【问题描述】:
我正在尝试向 S3 REST API 发出 HEAD Object 请求,但我不断收到 403 Forbidden 错误,即使我在 S3 上拥有具有必要权限的策略设置。响应正文是空的,所以我认为这不是签名问题。我已经尝试对政策进行多次更改,但似乎没有任何效果。我可以正常 PUT 对象和 DELETE 对象,只是 HEAD 不起作用。
这是我的存储桶政策:
{
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam:: 999999999999:user/User"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::999999999999:user/User"
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:DeleteObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
有什么想法吗?
更新:
正如迈克尔指出的那样,我的签名似乎有问题,尽管我看不出是什么。
def generate_url options={}
options[:action] = options[:action].to_s.upcase
options[:expires] ||= Time.now.to_i + 100
file_path = "/" + @bucket_name + "/" + options[:file_name]
string_to_sign = ""
string_to_sign += options[:action]
string_to_sign += "\n\n#{options[:mime_type]}\n"
string_to_sign += options[:expires].to_s
string_to_sign += "\n"
string_to_sign += file_path
signature = CGI::escape(
Base64.strict_encode64(
OpenSSL::HMAC.digest('sha1', SECRET_KEY, string_to_sign)
)
)
url = "https://s3.amazonaws.com"
url += file_path
url += "?AWSAccessKeyId=#{ACCESS_KEY}"
url += "&Expires=#{options[:expires]}"
url += "&Signature=#{signature}"
url
end
生成的要签名的字符串如下所示:
HEAD\n\n\n1418590715\n/video-thumbnails/1234.jpg"
解决方案:
似乎在开发文件 PUT 部分时,我实际上破坏了 GET 和 HEAD。我传递了一个空字符串作为请求的主体,而不是什么都不传递,而是在签名上创建了所需的 mime 类型并破坏了它,因为我没有提供 mime 类型。我只是删除了空的请求正文,它工作得很好。感谢 Michael 为我指出了错误的方向(我浪费了很多时间来更改存储桶策略)。
【问题讨论】:
-
那么,这个完全相同的代码适用于签署
GET请求,但不适用于同一对象的HEAD请求?我认为“video-thumbnails”是bucket,1234.jpg是key,US-Standard(us-east-1)是bucket所在的区域? -
正确。我使用基于查询的身份验证,这适用于 HEAD 请求吗?
标签: rest amazon-s3 http-status-code-403