使用 TAmazonStorageService.UploadObject 时 Content-type 为“text/*”时出现 SignatureDoesNotMatch 错误

Posted

技术标签:

【中文标题】使用 TAmazonStorageService.UploadObject 时 Content-type 为“text/*”时出现 SignatureDoesNotMatch 错误【英文标题】:SignatureDoesNotMatch error when Content-type is 'text/*' using TAmazonStorageService.UploadObject 【发布时间】:2012-05-06 23:05:11 【问题描述】:

使用以下 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 时总是出错:

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

仅当 Content-type 设置为“text/plain”、“text/html”或任何文本时才会发生这种情况。使用完全相同的代码,如果您只是将内容类型更改为任何其他内容类型,例如'video/3gpp',然后它按预期工作并且没有错误。正在上传的对象的实际内容不相关,并且与是否出现错误无关。

我已经在 Delphi 中跟踪过 Indy 代码,但我对为什么 text 内容类型总是给出这个错误感到困惑。

有什么想法吗?

【问题讨论】:

【参考方案1】:

如果您将“; charset=ISO-8859-1”附加到 Content-Type 字符串,那么它可以工作:

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

通过代码,我看到 TIdEntityHeaderInfo.SetHeaders (IdHTTPHeaderInfo.pas) 中的 Content-Type 正在更改,它是从 TIdHTTPProtocol.BuildAndSendRequest (IdHTTP.pas) 调用的。

最终,问题似乎在于 TIdEntityHeaderInfo.SetContentType (IdHTTPHeaderInfo.pas) 正在将字符集附加到内容类型(如果它是“文本”并且还没有字符集)。在这些情况下不应该更改内容类型,因为内容类型是要签名的字符串的一部分,因此在签名后更改它会使签名无效。

【讨论】:

很高兴您能够自己修复它。我在尝试上传 text/html 时遇到了同样的问题。当时我只使用了“html”——但是 Internet Explorer 在查看文件时遇到了问题。谢谢分享!!!!!!【参考方案2】:

我遇到了同样的问题。我也使用 application/octet-stream 作为内容类型,但还是遇到了一些麻烦。后来,我发现存储桶名称必须小写(在美国标准区域,Amazon 允许使用大写或混合大小写名称定义存储桶;但是,这些存储桶无法通过 HTTP API(包括 TAmazonStorageService)访问。而不是未找到消息,我仍然收到 403 错误(未经身份验证的用户)。 但是,我将名称更改为全小写,效果很好。 希望对你有帮助

【讨论】:

以上是关于使用 TAmazonStorageService.UploadObject 时 Content-type 为“text/*”时出现 SignatureDoesNotMatch 错误的主要内容,如果未能解决你的问题,请参考以下文章

第一篇 用于测试使用

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份