Mar*_*llo 7 rest amazon-s3 http-status-code-403
我正在尝试对S3 REST API执行HEAD对象请求但我仍然收到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/*"
}
]
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
更新:
正如迈克尔指出的那样,我的签名似乎是一个问题,尽管我没有看到什么.
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
Run Code Online (Sandbox Code Playgroud)
生成的要签名的字符串如下所示:
HEAD\n\n\n1418590715\n/video-thumbnails/1234.jpg"
Run Code Online (Sandbox Code Playgroud)
解:
在开发文件PUT时,似乎在某种程度上我实际上已经破坏了GET和HEAD.我传递一个空字符串作为请求的主体,而不是传递任何东西,使签名上需要mime类型并打破它,因为我没有提供mime类型.我只是删除了空的请求体,它工作得很好.谢谢迈克尔指出我的错误方向(我浪费了很多时间来改变存储桶策略).
仍然可能是您的签名,出于以下原因,我怀疑是这样的:
您对消息正文的观察是很好的观察;但是,这并不意味着您已得出结论。
在这种情况下,缺少响应正文根本不会给您任何有关错误性质的信息,因为无论如何,Web服务器都不应随HEAD响应一起返回正文:
该
HEAD方法与GET其他方法相同,除了服务器MUST NOT在响应中返回消息正文-http : //www.w3.org/Protocols/rfc2616/rfc2616-sec9.html(RFC-2616)
在我这方面进行测试,我确认S3对未签名HEAD请求和对错误签名HEAD请求的响应没有什么不同:它始终HTTP/1.1 403 Forbidden没有消息正文。
另请注意,的签名URL GET不适用于HEAD,反之亦然。
在S3 签名版本2和S3 签名版本4中,“要签名的字符串”包括“ HTTP动词” ,即为GET或HEAD,表示对其有效的签名GET无效HEAD,反之亦然...签名时必须知道request方法,因为它是签名过程中使用的元素。
该s3:GetObject权限是使用所需的唯一记录的权限HEAD,这似乎可以消除权限(如果有的话GET)的问题(如果正在运行),它可以将签名作为潜在问题。
对上面@Michael-sqlbot 的回答的附加评论......
我面临着相同的症状,但我有不同的根本原因。
如果您尝试 HEAD 一个不存在的文件,那么这也会返回 403 禁止错误,除非您拥有 s3:ListBucket 权限。
就我而言,我拥有 s3.GetObject、s3.PutObject 和 s3.HeadBucket 权限,但直到添加 s3.ListBucket 后,我才收到正确的 404 - 未找到错误。
此处也对此进行了解释: https: //aws.amazon.com/premiumsupport/knowledge-center/s3-rest-api-cloudfront-error-403/
| 归档时间: |
|
| 查看次数: |
8403 次 |
| 最近记录: |