当我设置包含“+”的响应标头覆盖时,为什么我的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替换
  • 在调用GetPreSignedURL()之前预先编码contentType,例如通过HttpUtility.UrlEncode方法 ,无论生成的URL的任何变化如何,都会产生无效的签名

鉴于此function已经存在多长时间,这有点令人惊讶,但我仍然认为它是一个错误 – 因此最好在Amazon Simple Storage Service论坛中查询此问题 。
更新:我刚刚意识到您已经在那里提出了相同的问题,并且确实已经确认了错误,因此可以通过监控AWS团队响应来确定正确的答案;)
更新:此错误已在SDK的1.4.1.0版本中修复 。