Почему мой предварительно подписанный запрос S3 недействителен, когда я установил переопределение заголовка ответа, которое содержит «+»? - PullRequest
6 голосов
/ 29 января 2012

Я использую 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

Обратите внимание, что в типе ответа-содержимого есть пробел, где теперь говорится image/svg xml вместо image/svg+xml. Мне кажется, что именно это является причиной проблемы, но как правильно ее исправить?

Должен ли я кодировать мой тип контента? Заключить это в кавычки или что-то? Документация ничего не говорит об этом.

Ответы [ 2 ]

5 голосов
/ 31 января 2012

Обновление

Эта ошибка была исправлена ​​в Версии 1.4.1.0 SDK.


Обход

Это подтвержденная ошибка в AWS SDK , поэтому до тех пор, пока они не выпустят исправление, я собираюсь использовать этот хак, чтобы все заработало:

Укажите тип контента в точности так, как вы хотите, чтобы он выглядел в заголовке ответа. Итак, если вы хотите, чтобы 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));

Да, это грязный обходной путь, но, эй, он работает для меня! :)

3 голосов
/ 30 января 2012

Странно, на самом деле - я смог легко воспроизвести это при следующем наблюдаемом поведении:

  • замена + в URL, сгенерированном GetPreSignedURL() его закодированной формой %2B, дает рабочий URL / подпись
    • это верно, независимо от того, заменяется ли / его закодированной формой %2F или нет
  • кодирование contentType заранее перед вызовом GetPreSignedURL(), например с помощью метода HttpUtility.UrlEncode возвращает недопустимые подписи независимо от любого варианта сгенерированного URL

Учитывая, как долго эта функциональность уже доступна, это несколько удивительно, но я все равно считаю, что это ошибка - соответственно, возможно, лучше всего запросить об этом в Amazon Simple Storage Service форум .
Обновление: Я только что понял, что вы уже задали тот же вопрос, и ошибка действительно была подтверждена, поэтому правильный ответ со временем можно выяснить, наблюдая за ответом команды AWS ;)
Обновление: Эта ошибка была исправлена ​​в Версии 1.4.1.0 SDK.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...