2012-01-27 64 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

相關問題