2012-01-27 2 views
3

코드가 옳은지, 잘못 됐는지를 모르겠습니다. 내가 프로그램 오류가 403 발생 실행하려고 ..델파이로 아마존 API에 요청하십시오 : HTTP/1.1 403 금지 됨

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

여기가 우리에게 보여주는 실제 개인 키입니까? –

+0

아니, 그건 내 진짜 개인 키가 아니야 ... 나 한테 샘플이있어? –

답변

6

아마존은 실제로 403 오류가 발생한 이유를 정확하게 설명하는 XML 문서를 다시 전송합니다. 메시지를 보는 가장 쉬운 방법은 Fiddler을 사용하고 127.0.0.1을 프록시로 사용하도록 Indy HTTP를 설정하는 것입니다. 그런 식으로 모든 트래픽이 피 들러를 통과하면 보낸 메일과 아마존 메일이 모두 표시됩니다.

Amazon S3 서비스에서 작동하도록 REST API를 구현할 때 서명해야하는 "Canonical Headers"를 알아 내는데 문제가있었습니다. Amazon API가 서명 한 텍스트를 다시 보내면 서명을 테스트 할 수 있으므로 바이트 단위로 비교할 수 있으므로 잘못 수행했는지 파악할 수 있습니다. 이 헤더를 준비하는 것과 정확히 같은 "표준 헤더"를 준비하지 않으면 분명히 403이됩니다. 예를 들어 Amazon이 사용하는 행 분리 기호는 LINEFEED (#10)입니다. TMemo에 헤더를 넣기 때문에 Windows 스타일의 CRLF 구분자를 사용하게됩니다. 이것만으로도 코드가 실패하기에 충분합니다.

다른 문제는 Indy 요청으로 추가 헤더를 보내는 것입니다. 나는 온라인 API 샘플을 따라 가면서 내가 보내야 할 사항과 Amazon이 대답해야 할 내용을 살펴 보았습니다. 피들러는 내가 보내고 있다고 생각했던 것과는 반대로 내가 실제로 보내고있는 것을 실제로 테스트하고 볼 수있는 유일한 방법이었습니다. 예를 들어 실수로 내 맞춤 헤더를 작성하는 데 TIdHttp.Request.RawHeaders을 사용했지만 요청이 준비되는 동안 해당 헤더가 플러시됩니다. 내 머리글을 TIdHttp.Request.CustomHeaders에 써야했는데, Fiddler의 도움 없이는 실제로 헤더를 보내지 않을 것입니다. 내 코드는 괜찮아 보였다.

+0

피 들러를 먼저 시험해보고, 나는 돌아와서 나의 결과를보고 할 것이다. –

+3

또는, 'TIdHTTP'는 코드에서 XML에 접근 할 수있게 해준다. '403' 답장은'EIdHTTPProtocolException' 예외를 발생시킵니다. XML은'EIdHTTPProtocolException.ErrorMessage' 속성에 있습니다. –

+3

또한 'TIdLogFile'또는 'TIdLogEvent'와 같은 인디 자신의'TIdLog ... '구성 요소를 사용하여'TIdHTTP '가 소켓 레이어에서 보내고받는 것을 정확히 볼 수 있습니다. –