使用delphi向Amazon API请求:得到HTTP/1.1 403 Forbidden

问题描述 投票:0回答: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
amazon-web-services delphi
1个回答
6
投票

亚马逊实际上会发回一个 XML 文档,其中准确描述了您收到 403 错误的原因。查看消息的最简单方法是使用 Fiddler 并将您的 Indy HTTP 设置为使用

127.0.0.1
作为代理。这样您的所有流量都会通过 Fiddler,您将看到您发送的内容和亚马逊返回的内容。

当我实现 REST API 以与 Amazon S3 服务配合使用时,我在确定需要签名的“规范标头”时遇到了一些问题。令人高兴的是,Amazon API 会向您发送回他们正在签名的文本来测试您的签名,这样您就可以逐字节进行比较并找出是否做错了。如果未能按照准备这些标头的方式完全准备这些“规范标头”,显然会导致

403
。例如,亚马逊使用的行分隔符是 LINEFEED (
#10
)。由于您将标题放入
TMemo
中,因此您将获得 Windows 风格的 CRLF 分隔符。仅此一点就足以让您的代码失败。

我遇到的另一件事是通过我的 Indy 请求发送额外的标头。我正在跟踪在线 API 示例,查看我应该发送的内容以及亚马逊应该回答的内容。 Fiddler 是实际测试和查看我发送的内容(而不是我认为发送的内容)的唯一方法。例如,我错误地使用

TIdHttp.Request.RawHeaders
来编写自定义标头,但在准备请求时这些标头会被刷新。我应该将我的标头写入
TIdHttp.Request.CustomHeaders
- 但如果没有 Fiddler 的帮助,我不会知道我实际上没有发送我的标头。我的代码看起来很好。

© www.soinside.com 2019 - 2024. All rights reserved.