我需要从必须正确设置时钟的计算机上将文件上传到S3,并且与正确时间的偏差会有所不同。您显然可以通过指定X-Amz-Date
标头(将其设置为当前实际时间)并使用查询字符串授权上载来实现。 aws-sdk
Ruby宝石没有在其presigned_url
方法中公开此参数,因此我尝试使用aws-sigv4
宝石来实现。但是,我的PUT
被拒绝,出现了403 Unauthorized
错误。
这是我尝试过的代码:
def upload_file_with_time(file, file_path, expires_in_seconds, time)
region = "us-east-1"
access_key_id = ENV['AWS_ACCESS_KEY_ID']
secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
obj = s3_bucket.object(file_path)
signer = Aws::Sigv4::Signer.new(
service: 's3',
region: region,
access_key_id: access_key_id,
secret_access_key: secret_access_key
)
pre_signed_url = signer.presign_url(
http_method: 'PUT',
url: obj.public_url,
expires_in: expires_in_seconds,
time: time
)
Net::HTTP.start(pre_signed_url.host) do |http|
http.send_request("PUT", pre_signed_url.request_uri, file, "content-type": "")
end
end
代码会生成一个这样的预签名URL:
https://XXXXX.s3.amazonaws.com/testing/89254661-24de-4bc7-b6e1-7d0018213735.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=XXXXX%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20190301T213824Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=XXXXX
(敏感信息已用XXXXX
编辑)。
当我尝试上传到此端点时,我从403 Unauthorized
获得了http.send_request
。如果我用来自curl
的帖子打URL,我将其视为XML响应的开始:
<?xml version=“1.0”?>
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
我在做什么错了?
答案 0 :(得分:0)
我需要从必须正确设置时钟的机器上将文件上传到S3。
时间是过去还是将来?尽管可能性很小,但这可能会引起问题(不过文档中没有显示相同的意思)。
但是,我发现您正在使用Net::HTTP
软件包并发出原始PUT请求,并且您用于生成预签名URL的方法对我来说并不十分令人信服,因为obj.public_url
的内容。
无论如何,我确实有这样的要求(预先上传URL,但没有“机器上的时间不正确”部分)。这是我使用并有效的指南:
https://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjectPreSignedURLRubySDK.html
该页面上有一个有效的代码(不粘贴到这里,因为将来可能会更改)对我有用。