Ошибка SignatureDoesNotMatch, когда тип содержимого - "text/*" с использованием TAmazonStorageService.UploadObject


Используя следующий код Delphi XE2 (update 4):

var
  ConInfo: TAmazonConnectionInfo;
  RespInfo: TCloudResponseInfo;
  Service: TAmazonStorageService;
  Content: TBytes;
  Headers: TStringList;
begin
  ConInfo:=TAmazonConnectionInfo.Create(self);
  ConInfo.AccountName:='YOUR ACCOUNT NAME';
  ConInfo.AccountKey:='YOUR ACCOUNT KEY';
  ConInfo.Protocol:='http';

  Service:=TAmazonStorageService.Create(ConInfo);
  RespInfo:=TCloudResponseInfo.Create;

  SetLength(Content, 128);
  FillMemory(@Content[0], 128, Byte('x'));

  Headers:=TStringList.Create;
  Headers.Values['Content-type']:='text/plain';
  if not Service.UploadObject('YOUR BUCKET', 'test.txt', Content, TRUE, nil, Headers, amzbaPrivate, RespInfo) then
    ShowMessage('Failed:' + RespInfo.StatusMessage);

Я всегда получаю ошибку при вызове UploadObject:

Failed: HTTP / 1.1 403 Forbidden-вычисленная нами сигнатура запроса не соответствует предоставленной вами подписи. Проверьте ваш ключ и подпись метод. (SignatureDoesNotMatch)

Это происходит только в том случае, если для типа содержимого задано значение "text/plain", "text/html" или "text anything". Используя точно такой же код, если вы просто измените тип контента на любой другой тип контента, например "video/3gpp", тогда он работает как ожидалось и без ошибок. Фактическое содержимое загружаемого объекта не имеет отношения к делу и не влияет на получение ошибки или нет.

Я проследил инди-код в Delphi, но я в тупике, почему тип текстового контента всегда выдает эту ошибку.

Есть идеи?

2 6

2 ответа:

Если вы добавляете "; charset=ISO-8859-1 " к строке типа содержимого, то это работает:

Headers.Values['Content-type']:='text/plain; charset=ISO-8859-1';

Проходя через код, я вижу, что тип контента изменяется в TIdEntityHeaderInfo.SetHeaders (IdHTTPHeaderInfo.pas), который называется от TIdHTTPProtocol.BuildAndSendRequest (IdHTTP.первенство).

В конечном счете, похоже, что проблема заключается в том, что TIdEntityHeaderInfo.SetContentType (IdHTTPHeaderInfo.pas) - это добавление набора символов к типу контента, если это "текст", а это не так. уже есть один. В таких ситуациях не следует изменять тип содержимого, так как тип содержимого является частью подписываемой строки, поэтому его изменение после подписания делает подпись недействительной.

У меня была та же самая проблема. Я также использовал application / octet-stream в качестве типа контента, но все еще имел некоторые проблемы. Позже я обнаружил, что имена ведер должны быть в нижнем регистре (в стандартном регионе США Amazon позволяет определять ведра с именами прописных или смешанных регистров; однако эти ведра недоступны через HTTP API (включая TAmazonStorageService). Вместо сообщения "не найдено" я получил сообщение об ошибке 403 (не прошедший проверку подлинности пользователь). Правда, один я поменял название на всех в нижнем регистре он работал отлично. Надеюсь, это поможет