S3 REST API HEAD请求上的403禁止错误 [英] 403 forbidden error on S3 REST API HEAD request

查看:311
本文介绍了S3 REST API HEAD请求上的403禁止错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试向S3 REST API发出HEAD Object请求,但是即使我设置了具有S3必要权限的策略,我仍然收到403 Forbidden错误.响应主体为空,因此我认为它不是签名问题.我已经尝试过对该政策进行多次更改,但似乎没有任何效果.我能够正常放置对象和删除对象,只是HEAD不起作用.

Im trying do do a HEAD Object request to the S3 REST API but I keep getting a 403 Forbidden error, even though I have the policy setup with the necessary permissions on S3. The response body is empty, so I don't think its a signature problem. I've tried several changes to the policy, nothing seems to make it work. I'm able to PUT objects and DELETE objects normally, just HEAD doesn't work.

这是我的存储桶策略:

{
"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/*"
    }
]
}

有什么想法吗?

更新:

就像迈克尔指出的那样,我的签名似乎有问题,尽管我看不到.

As Michael pointed out it seems to be a problem with my signature, though Im failing to see what.

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

生成的要签名的字符串如下所示:

The generated string to sign looks like this:

HEAD\n\n\n1418590715\n/video-thumbnails/1234.jpg"

解决方案:

似乎在开发文件PUT部分时,我实际上已经破坏了GET和HEAD.我正在传递一个空字符串作为请求的主体,而不是不传递任何内容,而是使签名上需要的mime类型并破坏了它,因为我没有提供mime类型.我只是删除了空的请求主体,它运行良好.感谢Michael为我指出的错误方向(我浪费了太多时间更改存储桶策略).

It seems at some point while developing the file PUT part I actually have broken GET and HEAD. I was passing an empty string as the body of the request, instead of passing nothing, making the mime type required on the signature and breaking it because I was providing no mime type. I simply removed the empty request body and it worked perfectly. Thanks Michael for pointing me out of the wrong direction I was(I wasted so much time changing the bucket policy).

推荐答案

它仍然可能是您的签名,由于以下原因,我怀疑是这样的:

It still could be your signature, and I suspect that it is, for the following reasons:

您对消息正文是一个很好的观察结果的观察;但是,这并不意味着您已得出结论.

Your observation that the message body is a good observation; however, it doesn't mean what you have concluded it means.

在这种情况下,缺少响应正文根本不会给您任何有关错误性质的信息,因为无论如何,Web服务器都不应随HEAD响应一起返回正文:

The lack of a response body does not give you any information at all about the nature of the error, in this case, because a web server is not supposed to return a body along with a HEAD response, no matter what:

HEAD方法与GET相同,除了服务器MUST NOT在响应中返回消息正文

The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response

- http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html (RFC-2616)

— http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html (RFC-2616)

从我这一边进行测试,我确认S3对未签名的HEAD请求和对错误签名的HEAD请求的响应没有什么不同:它始终是HTTP/1.1 403 Forbidden,没有消息正文.

Testing this on my side, I've confirmed that S3's response to an unsigned HEAD request and to an incorrectly-signed HEAD request is no different: it's always HTTP/1.1 403 Forbidden with no message body.

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

Note, also, that a signed URL for GET is not valid for HEAD, and vice versa.

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

In both S3 Signature Version 2 and S3 Signature Version 4, the "String to Sign" includes the "HTTP Verb," which would be GET or HEAD, meaning that a signature that's valid for GET would not be valid for HEAD, and vice versa... the request method must be known at the time of signing, because it's an element that's used in the signing process.

s3:GetObject权限是唯一的记录的权限使用HEAD是必需的,如果GET在工作,这似乎可以消除权限问题,这将指向签名,这是潜在的问题.

The s3:GetObject permission is the only documented permission required for using HEAD, which seems to eliminate permissions as the problem, if GET is working, which points back to the signature as the potential issue.

这篇关于S3 REST API HEAD请求上的403禁止错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆