如何通过IdHTTP检查与jsp站点的连接

时间:2014-09-17 06:14:23

标签: delphi indy indy10

我在Borland Delphi 7中有一个使用Indy组件的程序,我想检查我的登录名和密码是否正确。

这是我目前的代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdHTTP, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack,
  IdSSL, IdSSLOpenSSL, IdCookieManager, StrUtils;

type
  TForm1 = class(TForm)
    IdHTTP1: TIdHTTP;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    Button1: TButton;
    Memo1: TMemo;
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
    IdCookieManager1: TIdCookieManager;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 post: TStringList;
 poczatek, koniec: integer;
 aStream: TMemoryStream;
 HTML, authToken: string;
 fLogin, fHaslo: string;
begin
 IdHTTP1.HandleRedirects := True;

 fLogin := Edit1.Text;
 fHaslo := Edit2.Text;

 HTML := IdHTTP1.Get('https://e-skok.pl/eskok/login.jsp');
 poczatek := Pos('name="atlassian-token" value="', HTML) +
 Length('name="atl_token" value="');
 koniec := PosEx('"', HTML, poczatek);
 authToken := copy(HTML, poczatek, koniec - poczatek);

 post := TStringList.Create;
 try
   post.Add('atlassian-token=' + authToken);
   post.Add('os_username=' + fLogin);
   post.Add('os_password=' + fHaslo);
 try
   IdHTTP1.Request.ContentType:= 'application/json';
   HTML:= IdHTTP1.Post('https://e-skok.pl/eskok/login.jsp', post);
   Memo1.Text:= HTML;
   Label1.Caption := 'YES';
 except
     if IdHTTP1.ResponseCode = 401 then
       begin
       ShowMessage('Nieprawidłowy login lub hasło.');
       Label1.Caption := 'NO';
       end
      else
      Label1.Caption := ':)';
 end;
 finally
   post.Free;
 end;
end;
end.

问题是当我尝试登录时,程序总是说“是”(这意味着它已连接,即使登录和/或密码错误)。

通过IdHTTP检查与jsp站点的连接的正确方法是什么?

1 个答案:

答案 0 :(得分:3)

您无法单独依靠ResponseCode来验证您的登录信息,尤其是涉及基于HTML的登录表单时。是的,Post()在返回HTTP错误代码时引发异常。因此Post()未引发异常的事实意味着服务器未报告HTTP错误。但它发回的内容可能是HTML错误页面,甚至是显示失败消息的登录页面(这并不罕见)。因此,当Post()"成功"时,您需要分析响应以确保它符合您的期望。

当我在网络浏览器中转到https://e-skok.pl/eskok/login.jsp并输入错误的凭据时,我会被重定向回https://e-skok.pl/eskok/login.jsp?err=1。当Post()退出时没有例外,您可以查看TIdHTTP.Response以查看这是否是重定向到的最后一个网址。

顺便说一句,您呼叫的TStringsPost()仅支持application/x-www-form-urlencoded个帖子,因此将Request.ContentType设置为application/json是错误的,因为您不是发布JSON格式的数据。幸运的是,Post()会使用正确的值替换ContentType。如果您确实要发布JSON数据,则必须使用TStream版本的Post()代替。

更新:在查看https://e-skok.pl/eskok/login.jsp的实际HTML后,我可以看到您最初显示的代码不正确。您没有正确解析登录HTML(没有atlassian-token字段存在),并且您使用错误的字段名称将凭据发布到错误的URL。您必须发布到https://e-skok.pl/eskok/j2_security_check,并且期望以下输入字段:

j_username
j_password
j_captcha_response

最后一个字段特别需要额外的工作,因为它是一个动态生成的验证码。您必须解析HTML以提取验证码图像的网址{https://e-skok.pl/eskok/captcha.jsp?d=1410970679796,每次请求页面时d都会更改),下载图像(您可以使用TIdHTTP.Get()那个)并将其显示在你应用的用户界面中,这样你就可以输入正确的文本值,在j_captcha_response字段中发布。

试试,然后用结果报告。