当我设置包含“+”的响应标头覆盖时,为什么我的S3预签名请求无效?
我正在使用Amazon .NET SDK生成预先签名的URL,如下所示:
public System.Web.Mvc.ActionResult AsActionResult(string contentType, string contentDisposition) { ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides(); headerOverrides.ContentType = contentType; if (!string.IsNullOrWhiteSpace(contentDisposition)) { headerOverrides.ContentDisposition = contentDisposition; } GetPreSignedUrlRequest request = new GetPreSignedUrlRequest() .WithBucketName(bucketName) .WithKey(objectKey) .WithProtocol(Protocol.HTTPS) .WithExpires(DateTime.Now.AddMinutes(6)) .WithResponseHeaderOverrides(headerOverrides); string url = S3Client.GetPreSignedURL(request); return new RedirectResult(url, permanent: false); }
这非常有效,除非我的contentType
包含一个+
。 当我尝试获取SVG文件时会发生这种情况,例如,它获取的内容类型为image/svg+xml
。 在这种情况下,S3会抛出SignatureDoesNotMatch
错误。
错误消息显示StringToSign
如下所示:
GET 1234567890 /blah/blabh/blah.svg?response-content-disposition=filename="blah.svg"&response-content-type=image/svg xml
请注意,response-content-type中有一个空格,现在它表示image/svg xml
而不是image/svg+xml
。 在我看来,这就是导致问题的原因,但是解决这个问题的正确方法是什么?
我应该编码我的内容类型吗? 将它包含在引号或其他内容中? 文档没有说明这一点。
更新
自SDK 1.4.1.0版起 ,此错误已得到修复 。
解决方法
这是AWS SDK中确认的错误 ,因此在他们发布修复程序之前我会使用此hack来使事情正常工作:
在响应标头中准确指定内容类型。 因此,如果您希望S3返回image/svg+xml
的内容类型,请将其设置为:
ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides(); headerOverrides.ContentType = "image/svg+xml";
现在,继续像往常一样生成预先签名的请求:
GetPreSignedUrlRequest request = new GetPreSignedUrlRequest() .WithBucketName(bucketName) .WithKey(objectKey) .WithProtocol(Protocol.HTTPS) .WithExpires(DateTime.Now.AddMinutes(6)) .WithResponseHeaderOverrides(headerOverrides); string url = S3Client.GetPreSignedURL(request);
最后,使用您的内容类型的正确URL编码值“修复”生成的URL:
url = url.Replace(contentType, HttpUtility.UrlEncode(contentType));
是的,这是一个肮脏的解决方法,但是,嘿,它对我有用! 🙂
确实很奇怪 – 我已经能够轻松地重现这一点,具有以下观察到的行为:
- 在
GetPreSignedURL()
生成的URL中用其编码forms%2B
替换+
产生一个有效的URL /签名- 这是正确的,无论是否用其编码forms
%2F
替换
- 这是正确的,无论是否用其编码forms
- 在调用
GetPreSignedURL()
之前预先编码contentType,例如通过HttpUtility.UrlEncode方法 ,无论生成的URL的任何变化如何,都会产生无效的签名
鉴于此function已经存在多长时间,这有点令人惊讶,但我仍然认为它是一个错误 – 因此最好在Amazon Simple Storage Service论坛中查询此问题 。
更新:我刚刚意识到您已经在那里提出了相同的问题,并且确实已经确认了错误,因此可以通过监控AWS团队响应来确定正确的答案;)
更新:此错误已在SDK的1.4.1.0版本中修复 。