And*_*ong 5 ruby-on-rails amazon-s3 amazon-web-services
我目前正在使用带有服务器端客户提供的加密密钥 (SSE-C) 的 Ruby aws-sdk 版本 2 gem。我可以毫无问题地将对象从 rails 表单上传到 Amazon S3。
def s3
Aws::S3::Object.new(
bucket_name: ENV['S3_BUCKET'],
key: 'hello',
)
end
def upload_object
customer_key = OpenSSL::Cipher::AES.new(256, :CBC).random_key
customer_key_md5 = Digest::MD5.new.digest(customer_key)
object_key = 'hello'
options = {}
options[:key] = object_key
options[:sse_customer_algorithm] = 'AES256'
options[:sse_customer_key] = customer_key
options[:sse_customer_key_md5] = customer_key_md5
options[:body] = 'hello world'
options[:bucket] = ENV['S3_BUCKET']
s3.put(options)
test_params = {
object_key: object_key,
customer_key: Base64.encode64(customer_key),
md5_key: Base64.encode64(customer_key_md5),
}
Test.create(test_params)
end
Run Code Online (Sandbox Code Playgroud)
但是我在检索对象并生成签名的 url 链接供用户下载时遇到了一些问题。
def retrieve_object(customer_key, md5)
options = {}
options[:key] = 'hello
options[:sse_customer_algorithm] = 'AES256'
options[:sse_customer_key] = Base64.decode64(customer_key)
options[:sse_customer_key_md5] = Base64.decode64(md5)
options[:bucket] = ENV['S3_BUCKET']
s3.get(options)
url = s3.presigned_url(:get)
end
Run Code Online (Sandbox Code Playgroud)
该链接已生成,但当我点击它时,它会将我定向到一个亚马逊页面。
<Error>
<Code>InvalidRequest</Code>
<Message>
The object was stored using a form of Server Side Encryption. The correct parameters must be provided to retrieve the object.
</Message>
<RequestId>93684EEBA062B1C2</RequestId>
<HostId>
OCnn5EG7ydfoKzsmEDMbqK5kOhLFpNXxVRdekfhOfnBc6s+jtPYFsKi8IZsEPcd9ConbYUHgwC8=
</HostId>
</Error>
Run Code Online (Sandbox Code Playgroud)
错误消息没有帮助,因为我不确定需要添加哪些参数。我想我可能缺少一些权限参数。
获取方法 http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#get-instance_method
Presigned_Url 方法 http://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#presigned_url-instance_method
当您生成预签名的 GET 对象 URL 时,您需要提供要传递给 的所有相同参数Aws::S3::Object#get
。
s3.get(sse_customer_algorithm: 'AES256', sse_customer_key: customer_key).body.read
Run Code Online (Sandbox Code Playgroud)
这意味着您需要将相同的 sse_customer_* 选项传递给#presigned_url
:
url = obj.presigned_url(:get,
sse_customer_algorithm: 'AES256',
sse_customer_key: customer_key)
Run Code Online (Sandbox Code Playgroud)
这将确保开发工具包在您发出最终 GET 请求时正确签署 Amazon S3 期望的标头。下一个问题是您现在负责将这些值与 GET 请求一起作为标头发送。Amazon S3 不会接受查询字符串中的算法和密钥。
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri.request_uri, {
"x-amz-server-side-encryption-customer-algorithm" => 'AES256',
"x-amz-server-side-encryption-customer-key" => Base64.encode64(cpk),
"x-amz-server-side-encryption-customer-key-MD5" => Base64.encode64(OpenSSL::Digest::MD5.digest(cpk))
})
Run Code Online (Sandbox Code Playgroud)
请注意- 在测试时,我发现当前 v2.0.33 版本的aws-sdk
gem 的预签名 URL 实现中存在一个错误。该问题现已修复,一旦发布,应该会成为 v2.0.34 的一部分。
请参阅以下 gitst 以获取修补该错误并进行演示的完整示例:
您可以在此处查看示例脚本:
https://gist.github.com/trevorrowe/49bfb9d59f83ad450a9e
只需替换脚本顶部的bucket_name
和变量即可。object_key
归档时间: |
|
查看次数: |
1941 次 |
最近记录: |