2012-01-27 106 views
3

我不知道我的代码是对还是错。 当我尝试运行出现程序错误403 ..向delphi请求Amazon API:得到HTTP/1.1 403 Forbidden

unit Unit1; 
interface 
uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs,ssbase64, StdCtrls,secutils,OmniXMLUtils,OmniXML, xmldom, 
    XMLIntf, msxmldom, XMLDoc, IdBaseComponent, IdComponent, IdTCPConnection, 
    IdTCPClient, IdHTTP,IdURI; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    Memo1: TMemo; 
    XMLDocument1: TXMLDocument; 
    IdHTTP1: TIdHTTP; 
    Memo2: TMemo; 
    Memo3: TMemo; 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 
implementation 
{$R *.dfm} 
function MyEncodeUrl(source:string):string; 
var i:integer; 
begin 
    result := ''; 
    for i := 1 to length(source) do 
     if not (source[i] in ['A'..'Z','a'..'z','0','1'..'9','-','_','~','.']) then result := result + '%'+inttohex(ord(source[i]),2) else result := result + source[i]; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    uhost,uri,public_key, private_key,signature,timestamp,string_to_sign : string; 
    request : String; 
begin 
uhost := 'ecs.amazonaws.com'; 
uri := 'onca/xml'; 
public_key := '1ETPTJHQ37P671HNXXX'; 
private_key  := 'j4JtMHQwL6wR39fy2CJgNfHibLjK9GsC5Z6XXXX'; 
timestamp  := MyEncodeUrl(XMLDateTimeToStr(now)); 
string_to_sign := 'AWSAccessKeyId=1ETPTJHQ37P671HN9282'; 
string_to_sign := string_to_sign+ '&AssociateTag=moc-20&ItemPage=1&Keywords=kitchen%20aid&Operation=ItemSearch&ResponseGroup=Large&SearchIndex=Kitchen&'; 
string_to_sign := string_to_sign+'service=AWSECommerceService&Timestamp='+timestamp; 
string_to_sign := string_to_sign+'&Version=2009-03-31'; 

Memo1.Clear; 
Memo1.Lines.Append('GET'); 
Memo1.Lines.Append('ecs.amazonaws.com'); 
Memo1.Lines.Append('/onca/xml'); 
Memo1.Lines.Append(string_to_sign); 

signature := StrToMime64(HMACString(haSHA256, private_key, 32, Memo1.Text)); 
request := 'http://ecs.amazonaws.com/onca/xml?AWSAccessKeyId=1ETPTJHQ37P671HN9282'; 
request := request+ '&AssociateTag=moc-20&ItemPage=1&Keywords=kitchen%20aid&Operation=ItemSearch&ResponseGroup=Large&SearchIndex=Kitchen&'; 
request := request+'service=AWSECommerceService&Timestamp='+timestamp; 
request := request+'&Version=2009-03-31'; 
request := request+'&Signature='+signature; 

Memo1.Text := IdHTTP1.Get(request); 
end; 
end. 

任何机构可以跟踪我的错误?

FYI :: 
Delphi 7 with build in Indy; 
use OmniXML to generate timestamp 
use OpenStrSecII to generate signature 
+5

这是您真正的私钥吗? – 2012-01-27 09:36:27

+0

不,这不是我真正的私钥... 你有样品给我吗? – 2012-01-27 13:17:41

回答

6

亚马逊实际上发回了一个XML文档,该文档准确地描述了您为什么得到403错误。查看邮件的最简单方法是使用Fiddler,并将Indy HTTP设置为使用127.0.0.1作为代理。这样所有的流量都通过Fiddler,你会看到你发送的和Amazon返回的。

当我实现了我的REST API以使用Amazon S3服务时,我发现了一些问题,找出需要签名的“规范头文件”。令人高兴的是,Amazon API会将您签名的文本发回给您,以便测试您的签名,因此您可以逐字比较并确定您是否做错了。如果没有准备好那些“标准标题”,就像准备标题一样,显然会导致403。例如,亚马逊正在使用的行分隔符是LINEFEED(#10)。由于您将标题放在TMemo中,因此您将获得Windows风格的CRLF分隔符。这足以让你的代码失败。

我遇到的其他问题是使用我的Indy请求发送额外的头文件。我正在关注在线API示例,查看我应该发送的内容以及亚马逊应该回答的问题。 Fiddler是真正测试并看到我发送的内容的唯一方式,而不是我以为我发送的内容。例如,我错误地使用TIdHttp.Request.RawHeaders来编写我的自定义标题,但是在请求准备好时这些标题被刷新。我应该写我的标题TIdHttp.Request.CustomHeaders - 但没有提琴手的帮助,我不知道我实际上并没有发送我的标题。我的代码看起来很好。

+0

首先尝试提琴手,我会回来,并报告我的结果。 – 2012-01-27 12:05:26

+3

或者,'TIdHTTP'可以让你访问你的代码中的XML。一个'403'回复会引发一个'EIdHTTPProtocolException'异常。该XML将位于'EIdHTTPProtocolException.ErrorMessage'属性中。 – 2012-01-27 19:33:35

+3

此外,您可以使用Indy自己的'TIdLog ...'组件,比如'TIdLogFile'或'TIdLogEvent',来确切查看'TIdHTTP'在套接字层发送和接收的内容。 – 2012-01-27 19:35:03

相关问题