我不知道我的代码是对还是错。 当我尝试运行程序时出现错误 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
亚马逊实际上会发回一个 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 的帮助,我不会知道我实际上没有发送我的标头。我的代码看起来很好。