使用TAmazonStorageService.UploadObject上传'text/*'类型的内容时出现SignatureDoesNotMatch错误

6
使用以下Delphi XE2(更新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 时,我总是遇到错误:

失败:HTTP/1.1 403 禁止 - 我们计算的请求签名与您提供的签名不匹配。请检查您的密钥和签名方法。(SignatureDoesNotMatch)

只有当 Content-type 设置为 'text/plain'、'text/html' 或任何文本内容时才会出现这种情况。如果您使用完全相同的代码,只是将 content-type 更改为其他任何 content-type,例如 'video/3gpp',那么它就能正常工作且没有错误。上传的对象的实际内容并不相关,也不影响是否出现错误。

我已经跟踪了 Delphi 中的 Indy 代码,但我对于为什么文本内容类型总是出现此错误感到困惑。

有什么想法吗?

2个回答

4
如果你在Content-Type字符串后面添加“; charset=ISO-8859-1”,那么它就可以正常工作:
Headers.Values['Content-type']:='text/plain; charset=ISO-8859-1';

通过代码的调试,我发现 Content-Type 被更改的地方在 TIdEntityHeaderInfo.SetHeaders (IdHTTPHeaderInfo.pas) 中,该方法被 TIdHTTPProtocol.BuildAndSendRequest (IdHTTP.pas) 调用。

最终看起来问题出在 TIdEntityHeaderInfo.SetContentType (IdHTTPHeaderInfo.pas) 上,如果内容类型为 'text' 并且没有字符集,那么它会附加一个字符集。在这些情况下,它不应该更改内容类型,因为内容类型是要签名的字符串的一部分,所以在签名后更改它将导致签名无效。


很高兴你能自己解决它。我在尝试上传 text/html 时遇到了完全相同的问题。当时我只使用了“html” - 但是然后 Internet Explorer 在查看文件时出现了问题。谢谢分享!!!!! - M Schenkel

0

我也曾遇到同样的问题。我也使用了application/octet-stream作为内容类型,但仍然遇到一些麻烦。后来,我发现存储桶名称必须全部小写(在US Standard Region中,Amazon允许定义具有大写或混合大小写名称的存储桶;但是,这些存储桶无法通过HTTP API(包括TAmazonStorageService)进行访问。我仍然收到了403错误(未经身份验证的用户)而不是“未找到”消息。 但是,一旦我将名称更改为全部小写,它就可以正常工作了。 希望能有所帮助


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接