我正在尝试通过delphi / indy登录网站。目前我只有一个按钮(用于发送密码/用户名),它调用此程序。
procedure TForm5.Login(name: string; Pass: string);
var
UserID :string;
Password :string;
res :TStringStream;
details :Tstringlist;
multiformupload: TIdMultiPartFormDataStream;
begin
//create ini file to hold password / usesr name
UserID:=name;
Password:=pass;
Res := TStringStream.Create();
MultiFormUpload := TIdMultiPartFormDataStream.Create;
MultiFormUpload.AddFormField('user',UserID);
MultiformUpload.AddFormField('pass',Password);
idhttp1.Request.ContentType := '8bit';
//idhttp1.Get('http://codeelf.com',res);
idhttp1.Post('http://codeelf.com/games/the-grid-2/grid',Multiformupload,res);
memo1.Lines.LoadFromStream(res);
res.Free;
end;
当我查看网站代码时,我有这个。
<form id="gridForm" action="" method="post" onsubmit="return checkLoginForm()">
<table align="left" border="0" cellspacing="2" cellpadding="2">
<tr>
<td align="left" id="my_username">Username:</td>
<td align="right"><input type="text" id="user" name="user" maxlength="12" autocomplete="off" /></td>
</tr>
<tr>
<td align="left" id="my_password">Password:</td>
<td align="right"><input type="password" id="pass" name="pass" maxlength="20" /></td>
</tr>
<tr>
<td colspan="2" align="right">
</td>
</tr>
<tr>
<td colspan="2" align="right">
<input id="submission" type="submit" class="button" name="sublogin" value="Login" /></td>
</tr>
因此提交按钮值只是登录。因此,我不知道POST数据的位置。我怎么能找到这个?一旦我找到了网址,我应该能够将其添加到idhttp1.Post
正确吗?
答案 0 :(得分:2)
您的代码存在一些问题:
您没有提交登录表单中的所有内容。你必须这样做。这包括登录按钮本身的值,因为它分配了name
和id
值。有些服务器需要按钮值。
您将TIdHTTP.Request.ContentType
设置为无效值。但是,TIdHTTP.Post(TIdMultipartFormDataStream)
忽略用户提供的ContentType
并使用TIdMultipartFormDataStream.RequestContentType
属性。所以这不会影响您的登录,但它仍然是您的代码中的错误。
在将响应数据加载到TMemo
时,您忽略了响应的字符集。您应该使用返回TIdHTTP.Post()
的重载版String
并将其分配给TMemo.Text
属性。让TIdHTTP
为您处理字符集解码。
您正在泄漏TIdMultipartFormDataStream
对象。
试试这个:
procedure TForm5.Login(name: string; Pass: string);
var
MultiFormUpload: TIdMultiPartFormDataStream;
begin
MultiFormUpload := TIdMultiPartFormDataStream.Create;
try
MultiFormUpload.AddFormField('user', name);
MultiFormUpload.AddFormField('pass', pass);
MultiFormUpload.AddFormField('sublogin', 'Login');
//IdHTTP1.Get('http://codeelf.com');
Memo1.Text := IdHTTP1.Post('http://codeelf.com/games/the-grid-2/grid', MultiFormUpload);
finally
MultiFormUpload.Free;
end;
end;
话虽这么说,有些服务器在请求登录页面时向客户端发送cookie,然后这些cookie需要在登录过程中发回。如果单独发布到登录URL不起作用,请先尝试检索登录页面,然后发布登录凭据,让TIdHTTP
为您处理cookie:
procedure TForm5.Login(name: string; Pass: string);
var
MultiFormUpload: TIdMultiPartFormDataStream;
begin
MultiFormUpload := TIdMultiPartFormDataStream.Create;
try
MultiFormUpload.AddFormField('user', name);
MultiFormUpload.AddFormField('pass', pass);
MultiFormUpload.AddFormField('sublogin', 'Login');
IdHTTP1.Get('http://codeelf.com/games/the-grid-2/grid', TStream(nil));
Memo1.Text := IdHTTP1.Post('http://codeelf.com/games/the-grid-2/grid', MultiFormUpload);
finally
MultiFormUpload.Free;
end;
end;
更新:原始代码还有其他问题。 HTML登录表单不会要求multipart/form-data
帖子开头,因此TIdMultipartFormDataStream
是使用的错误类。请改用TStringList
,以便TIdHTTP.Post()
发送application/x-www-form-urlencoded
帖子:
procedure TForm5.Login(name: string; Pass: string);
var
Params: TStringList;
begin
Params := TStringList.Create;
try
Params.Add('user='+name);
Params.Add('pass='+pass);
Params.Add('sublogin=Login');
//IdHTTP1.Get('http://codeelf.com');
Memo1.Text := IdHTTP1.Post('http://codeelf.com/games/the-grid-2/grid', Params);
finally
Params.Free;
end;
end;
答案 1 :(得分:1)
POST必须转到您检索HTML页面的同一URL,因为action属性为空。
根据服务器的不同,成功登录会将cookie发送回客户端,需要包含在下一个请求中。
如果您使用Firebug或Fiddler等HTTP代理工具分析浏览器/客户端通信,则可以找到或不使用更好的cookie。
如果服务器使用代理,则需要为客户端代码添加cookie支持。 Indy透明地支持HTTP cookie(TIdCookieManager)。