AWS开发人员博客中的这篇文章介绍了如何为将在服务器端加密的S3文件生成预先签名的URL:https://aws.amazon.com/blogs/developer/generating-amazon-s3-pre-signed-urls-with-sse-kms-part-2/。描述如何生成URL的部分是有意义的,但随后文章继续描述如何在put请求中使用url,并且它说除了生成的url之外,还必须添加到http请求中标头指定加密算法。当加密算法包含在url的生成中时,为什么这是必要的?
// Generate a pre-signed PUT URL for use with SSE-KMS
GeneratePresignedUrlRequest genreq = new GeneratePresignedUrlRequest(
myExistingBucket, myKey, HttpMethod.PUT)
.withSSEAlgorithm(SSEAlgorithm.KMS.getAlgorithm());
...
HttpPut putreq = new HttpPut(URI.create(puturl.toExternalForm()));
putreq.addHeader(new BasicHeader(Headers.SERVER_SIDE_ENCRYPTION,
SSEAlgorithm.KMS.getAlgorithm()));
我问的部分原因是好奇,但也因为在我的情况下必须执行put请求的代码运行在与生成url的机器不同的机器上。我不会详细介绍,但确保一台机器生成的标题与另一台机器生成的URL匹配真的很麻烦。
答案 0 :(得分:0)
看起来有关加密的信息未包含在预签名网址中。我猜测它包含在GeneratePresignedUrlRequest中的唯一原因是生成一个检查身份验证的哈希。在阅读了何时使用url参数与自定义标头的问题之后,我不得不怀疑S3是否有明确的理由使用自定义标头而不是url参数。正如原始问题中所提到的,必须包含这些标头会使使用此API变得困难。如果使用url参数,我不会遇到这个问题。对此事的任何评论都将不胜感激。
答案 1 :(得分:0)
我不知道理由是多么“明确”,但我的假设是加密参数需要作为标题发送,以防止它们出现在记录查询字符串的日志中。
为什么在加密算法包含在网址生成
中时,这是必要的
这方面更容易回答。签名请求是向系统证明拥有您的访问密钥秘密的人授权这个确切的特定请求,直到最后一个字节的方式。更改任何有关签名生成中包含的请求的内容,并且您已使签名无效,因为现在请求与授权的请求不同。
当S3收到您的请求时,它会查找您的密钥并完全按照您的本地代码执行操作...它会对收到的请求进行签名,并检查其生成的签名是否与您提供的签名相匹配。
一个常见的误解是签名的URL是由服务生成的,但它们不是。签名URL完全在本地生成。该算法在计算上不可能进行逆向工程,对于任何给定的请求,只有1个可能的有效签名。