C# 为什么当我设置包含“0”的响应头覆盖时,我的S3预签名请求无效+&引用;?
我正在使用Amazon.NET SDK生成一个预签名URL,如下所示:C# 为什么当我设置包含“0”的响应头覆盖时,我的S3预签名请求无效+&引用;?,c#,amazon-s3,C#,Amazon S3,我正在使用Amazon.NET SDK生成一个预签名URL,如下所示: public System.Web.Mvc.ActionResult AsActionResult(string contentType, string contentDisposition) { ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides(); headerOverrides.ContentType = cont
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);
}
GET 1234567890 /blah/blabh/blah.svg?response-content-disposition=filename="blah.svg"&response-content-type=image/svg xml
ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides();
headerOverrides.ContentType = "image/svg+xml";
除非我的contentType
中包含+
,否则此操作非常有效。例如,当我尝试获取SVG文件时,就会发生这种情况,该文件的内容类型为image/SVG+xml
。在这种情况下,S3抛出一个SignatureDesNotMatch
错误
错误消息显示如下所示的StringToSign
:
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);
}
GET 1234567890 /blah/blabh/blah.svg?response-content-disposition=filename="blah.svg"&response-content-type=image/svg xml
ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides();
headerOverrides.ContentType = "image/svg+xml";
请注意,响应内容类型中有一个空格,它现在表示image/svgxml
,而不是image/svg+xml
。在我看来,这似乎是造成问题的原因,但什么是解决问题的正确方法呢
我应该对我的内容类型进行编码吗?用引号或别的什么把它括起来?文档中没有提到这一点。的确很奇怪-我可以通过以下观察到的行为很容易地重现这一点:
- 将
中由+
生成的URL替换为其编码形式GetPreSignedURL()
将生成一个工作URL/签名%2B
- 无论是否将
替换为其编码形式/
,这都是正确的%2F
- 无论是否将
- 在调用
之前预先编码contentType(例如通过),无论生成的URL有何变化,都会产生无效签名GetPreSignedURL()
给定这个函数的可用性有多长,这有点令人惊讶,但我仍然认为它是一个bug——因此,最好在.BR>中对此进行查询。
更新:我刚刚意识到你已经在那里问了同样的问题,错误确实得到了确认,因此可以通过监视;)来找出正确的答案
更新:此错误已被SDK删除。
变通办法 这是一个已确认的问题,因此,在他们发布修复程序之前,我将使用此黑客程序使其正常工作: 准确地指定内容类型,使其在响应标头中看起来像什么。因此,如果希望S3返回
image/svg+xml
的内容类型,请将其设置为如下所示:
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);
}
GET 1234567890 /blah/blabh/blah.svg?response-content-disposition=filename="blah.svg"&response-content-type=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));
是的,这是一个肮脏的解决办法,但是,嘿,它对我有效!:) 你完全正确。事实上,我尝试了你所做的一切,并在我发布问题后得出了相同的结论!:)虽然URL在编码时起作用,但我注意到响应中的实际内容类型标头有时会出错。