繁体   English   中英

403 S3 REST API HEAD请求上的禁止错误403

[英]403 forbidden error on S3 REST API HEAD request

我正在尝试对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/*"
    }
]
}

有任何想法吗?

更新:

正如迈克尔指出的那样,我的签名似乎是一个问题,尽管我没有看到什么。

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类型。 我只是删除了空的请求体,它工作得很好。 谢谢迈克尔指出我的错误方向(我浪费了很多时间来改变存储桶策略)。

它仍然可能是你的签名,我怀疑它是,原因如下:

你观察到信息体是一个很好的观察; 但是,这并不意味着你已经得出的结论意味着什么。

在这种情况下,缺少响应主体并不会提供有关错误性质的任何信息,因为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 ,没有消息体。

另请注意, GET的签名URL对HEAD无效,反之亦然。

在S3 签名版本2和S3 签名版本4中 ,“要签名的字符串”包括“HTTP谓词”,它将是GETHEAD ,这意味着对GET有效的签名对HEAD无效,反之亦然。 ...签名时必须知道请求方法,因为它是签名过程中使用的元素。

s3:GetObject权限是使用HEAD所需的唯一文档权限,如果GET正在工作,这似乎会消除权限,这会将签名作为潜在问题返回。

确认HEAD的预签名URL将获得403 Forbidden。 如果设置自定义标头,例如对象的内容类型。 403响应将不包含自定义标头,仍然获得application / xml。

关于@ Michael-sqlbot上面答案的补充评论......

我遇到了相同的症状,但我有不同的根本原因。

如果您正在尝试HEAD一个不存在的文件,那么这也将返回403-forbidden错误, 除非您拥有s3:ListBucket权限。

在我的情况下,我有s3.GetObject,s3.PutObject和s3.HeadBucket权限,但直到我添加了s3.ListBucket才得到正确的404 - 未找到错误。

这也在这里解释: https//aws.amazon.com/premiumsupport/knowledge-center/s3-rest-api-cloudfront-error-403/

有同样的问题,但有不同的根本原因 - 试图创建一个桶,而不是获得404,得到403.由于S3是全局命名空间,其他人已经创建了桶,所以虽然我有正确的权限和设置对于我的帐户,我仍然会从HEAD请求获得403。 解决方案是先检查存储桶是否全局存在,如果存在,请尝试使用其他存储桶名称。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM