Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
573 views
in Technique[技术] by (71.8m points)

c# - Why is my S3 pre-signed request invalid when I set a response header override that contains a "+"?

I'm using the Amazon .NET SDK to generate a pre-signed URL like this:

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);
}

This works perfectly, except if my contentType contains a + in it. This happens when I try to get an SVG file, for example, which gets a content type of image/svg+xml. In this case, S3 throws a SignatureDoesNotMatch error.

The error message shows the StringToSign like this:

GET 1234567890 /blah/blabh/blah.svg?response-content-disposition=filename="blah.svg"&response-content-type=image/svg xml

Notice there's a space in the response-content-type, where it now says image/svg xml instead of image/svg+xml. It seems to me like that's what is causing the problem, but what's the right way to fix it?

Should I be encoding my content type? Enclose it within quotes or something? The documentation doesn't say anything about this.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Update

This bug has been fixed as of Version 1.4.1.0 of the SDK.


Workaround

This is a confirmed bug in the AWS SDK, so until they issue a fix I'm going with this hack to make things work:

Specify the content type exactly how you want it to look like in the response header. So, if you want S3 to return a content type of image/svg+xml, set it exactly like this:

ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides();
headerOverrides.ContentType = "image/svg+xml";

Now, go ahead and generate the pre signed request as usual:

GetPreSignedUrlRequest request = new GetPreSignedUrlRequest()
  .WithBucketName(bucketName)
  .WithKey(objectKey)
  .WithProtocol(Protocol.HTTPS)
  .WithExpires(DateTime.Now.AddMinutes(6))
  .WithResponseHeaderOverrides(headerOverrides);

string url = S3Client.GetPreSignedURL(request);

Finally, "fix" the resulting URL with the properly URL encoded value for your content type:

url = url.Replace(contentType, HttpUtility.UrlEncode(contentType));

Yes, it's a dirty workaround but, hey, it works for me! :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...