使用 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有三种方式(不使用,动态使用,静态使用,默认是动态使用)