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

403 S3 REST API头请求上的禁止错误,rest,amazon-s3,http-status-code-403,Rest,Amazon S3,Http Status Code 403,我正在尝试向S3RESTAPI请求一个HEAD对象,但是我一直收到一个403禁止的错误,即使我在S3上有策略设置和必要的权限。响应主体是空的,所以我认为这不是签名问题。我尝试过对政策进行几次修改,但似乎没有任何效果。我可以正常放置和删除对象,只是头部不工作 这是我的政策: { "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam:: 999999

我正在尝试向S3RESTAPI请求一个HEAD对象,但是我一直收到一个403禁止的错误,即使我在S3上有策略设置和必要的权限。响应主体是空的,所以我认为这不是签名问题。我尝试过对政策进行几次修改,但似乎没有任何效果。我可以正常放置和删除对象,只是头部不工作

这是我的政策:

{
"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"
解决方案:


似乎在某个时候,当开发文件放置部分时,我实际上已经破坏了GET和HEAD。我将传递一个空字符串作为请求的主体,而不是什么也不传递,使签名上需要mime类型并将其破坏,因为我没有提供mime类型。我只是删除了空的请求主体,它工作得非常好。感谢Michael为我指出了错误的方向(我浪费了这么多时间更改桶策略)。

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

您对消息正文的观察是一个很好的观察;然而,这并不意味着你得出的结论是什么

在这种情况下,由于web服务器不应返回带有
头的
响应的正文,因此缺少响应正文根本不会为您提供有关错误性质的任何信息,无论:

HEAD
方法与
GET
方法相同,只是服务器
不能在响应中返回消息体

-(RFC-2616)

在我这方面进行测试,我已经确认S3对未签名的
HEAD
请求和错误签名的
HEAD
请求的响应没有什么不同:它总是
HTTP/1.1403被禁止,没有消息体

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

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


s3:GetObject
权限是使用
HEAD
所需的唯一权限,如果
GET
正在工作,则这似乎消除了权限问题,这表明签名是潜在问题。

确认了HEAD预签名的URL将被禁止403。 如果设置自定义标题,例如对象的内容类型。
403响应将不包含自定义标题,但仍会获取application/xml。

对上面@Michael sqlbot的回答的附加评论

我面临着相同的症状,但我有不同的根本原因

如果您试图读取一个不存在的文件,那么这也将返回403禁止的错误,除非您拥有s3:ListBucket权限

在我的例子中,我拥有s3.GetObject、s3.PutObject和s3.HeadBucket权限,但直到添加了s3.ListBucket,我才得到正确的404-notfound错误


这里也解释了这一点:

有相同的问题,但有不同的根本原因——我们试图创建一个bucket,但没有得到404,而是得到了403。由于S3是全局命名的,其他人已经创建了这个bucket,所以尽管我拥有正确的权限并设置了我的帐户,但我仍然可以从HEAD请求中获得403。解决方案是首先检查bucket是否全局存在,如果存在,请尝试其他bucket名称。

Michael,感谢您指出。请看编辑过的消息。@Marcello我看你已经接受了这个答案。我很感激,但是你发现问题了吗?那么,这个完全相同的代码适用于签名
GET
请求,而不是
HEAD
对同一对象的请求?我认为“视频缩略图”是存储桶,1234.jpg是关键,美国标准(US-east-1)是存储桶所在的区域?正确。Im使用基于查询的身份验证,这对HEAD请求有效吗?