delphi - 如何在delphi10中使用IdHTTP登录Instagram网站

标签 delphi authentication idhttp delphi-10.1-berlin

我正在尝试在 Delphi 中使用 idhttp 登录 Instagram 网站。 我使用谷歌浏览器开发者工具来获取数据,这是我到目前为止所尝试过的..

procedure TForm1.Button1Click(Sender: TObject);
var
  lHTTP: TIdHTTP;
  S,M : TStrings;
  IdSSL: TIdSSLIOHandlerSocketOpenSSL;
begin
  S := TStringList.Create;
  S.Add('username :' +Edit1.Text);
  S.Add('password :'+ Edit2.Text);
  lHTTP := TIdHTTP.Create(nil);
  lHTTP.ReadTimeout := 30000;
  lHTTP.HandleRedirects := True;
  IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(lHTTP);
  IdSSL.SSLOptions.Method := sslvTLSv1;
  IdSSL.SSLOptions.Mode := sslmClient;
  lHTTP.IOHandler := IdSSL;
  lHTTP.Request.CustomHeaders.Add('x-csrftoken:'+ Edit3.Text);
  lHTTP.Request.CustomHeaders.Add('x-instagram-ajax:1');
  lHTTP.Request.CustomHeaders.Add(' x-requested-with:XMLHttpRequest');
  lHTTP.Request.CustomHeaders.Add('referer:https://www.instagram.com/');
  lHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
  lHTTP.Request.UserAgent := 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36';
  lHTTP.Post('https://www.instagram.com/accounts/login/ajax/', S);
  Memo1.Lines.Add(lHTTP.Request.ToString);
end;

我现在手动获取访问 token ,只是为了测试代码。我收到 HTTP/1.1 403 Forbidden。!

更新

这是cookies信息..

Response Headers
set-cookie:csrftoken=e3YbQ1FobxgMGcLHRAkj****ML97psae; expires=Tue, 20-Jun-2017 19:09:21 GMT; Max-Age=31449600; Path=/
set-cookie:s_network=; expires=Tue, 21-Jun-2016 20:09:21 GMT; Max-Age=3600; Path=/
set-cookie:sessionid=IGSC3074cea6684a55981cc30d3c5222ed9e4675db0aa4665d3f5b7ed4ae09be01b6%3AugN5uNRztrtVarx6LuheBkv5tNuaVHrL%3A%7B%22_token_ver%22%3A2%2C%22_auth_user_id%22%3A348733484%2C%22_token%22%3A%22348733484%3A6dXogo2jTCkOf29JEUxHavzxqp9iUOr4%3Aa4f855cabbd5c5d2999538a8ec9093c6a59af65e7306998a5647341bdd691158%22%2C%22asns%22%3A%7B%225.37.149.220%22%3A28885%2C%22time%22%3A1466536160%7D%2C%22_auth_user_backend%22%3A%22accounts.backends.CaseInsensitiveModelBackend%22%2C%22last_refreshed%22%3A1466536160.338314%2C%22_platform%22%3A4%2C%22_auth_user_hash%22%3A%22%22%7D; expires=Mon, 19-Sep-2016 19:09:21 GMT; httponly; Max-Age=7776000; Path=/
set-cookie:ds_user_id=348733***; expires=Mon, 19-Sep-2016 19:09:21 GMT; Max-Age=


Request Headers
set-cookie:sessionid=IGSC3074cea6684a55981cc30d3c5222ed9e4675db0aa4665d3f5b7ed4ae09be01b6%3AugN5uNRztrtVarx6LuheBkv5tNuaVHrL%3A%7B%22_token_ver%22%3A2%2C%22_auth_user_id%22%3A348***484%2C%22_token%22%3A%22348733484%3A6dXogo2jTCkOf29JEUxHavzxqp9iUOr4%3Aa4f855cabbd5c5d2999538a8ec9093c6a59af65e7306998a5647341bdd691158%22%2C%22asns%22%3A%7B%225.37.149.220%22%3A28885%2C%22time%22%3A1466536160%7D%2C%22_auth_user_backend%22%3A%22accounts.backends.CaseInsensitiveModelBackend%22%2C%22last_refreshed%22%3A1466536160.338314%2C%22_platform%22%3A4%2C%22_auth_user_hash%22%3A%22%22%7D; expires=Mon, 19-Sep-2016 19:09:21 GMT; httponly; Max-Age=7776000; Path=/
set-cookie:ds_user_id=348733***; expires=Mon, 19-Sep-2016 19:09:21 GMT; Max-Age=7776000; Path=/

最佳答案

您没有正确填充TStringList。您需要使用 = 而不是 : 作为 name=value 分隔符。与 CustomHeaders.Add() 相同。在后一种情况下,我建议改用 CustomHeaders.Values[]

您还应该使用 Request.Referer 属性,而不是 CustomHeaders.Add()

在提交实际登录之前,需要首先请求包含登录表单的 HTML 页面并不罕见,以便可以捕获与 HTML 关联的任何 cookie 并与登录表单一起提交。 Instagram 也不异常(exception)。

此外,Request.ToString() 毫无意义,您根本不应该使用它。

最后,您正在泄漏您创建的对象。

话虽如此,试试这个:

procedure TForm1.Button1Click(Sender: TObject);
var
  lHTTP: TIdHTTP;
  IdSSL: TIdSSLIOHandlerSocketOpenSSL;
  Params : TStrings;
  Reply, Token: string;
  Cookie: TIdCookie;
begin
  Params := TStringList.Create;
  try
    Params.Add('username=' + Edit1.Text);
    Params.Add('password=' + Edit2.Text);

    lHTTP := TIdHTTP.Create(nil);
    try
      IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(lHTTP);
      IdSSL.SSLOptions.Method := sslvTLSv1;
      IdSSL.SSLOptions.Mode := sslmClient;
      lHTTP.IOHandler := IdSSL;

      lHTTP.ReadTimeout := 30000;
      lHTTP.HandleRedirects := True;

      // capture cookies first...
      // passing nil to ignore any response body data and not waste memory for it...
      lHTTP.Request.UserAgent := 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36';
      lHTTP.Get('https://www.instagram.com', TStream(nil));

      Cookie := lHTTP.CookieManager.CookieCollection.Cookie['csrftoken', 'www.instagram.com'];
      if Cookie <> nil then
        Token := Cookie.Value;

      // now submit the login webform...
      lHTTP.Request.CustomHeaders.Values['X-CSRFToken'] := Token;
      lHTTP.Request.CustomHeaders.Values['X-Instagram-AJAX'] := '1';
      lHTTP.Request.CustomHeaders.Values['X-Requested-With'] := 'XMLHttpRequest';
      lHTTP.Request.Referer := 'https://www.instagram.com/';
      lHTTP.Request.ContentType := 'application/x-www-form-urlencoded';
      lHTTP.Request.UserAgent := 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36';
      Reply := lHTTP.Post('https://www.instagram.com/accounts/login/ajax/', Params);

      Memo1.Text := Reply;
    finally
      lHTTP.Free;
    end;
  finally
    Params.Free;
  end;
end;

这是两个请求 1 生成的 HTTP 对话框:

1:我没有 Instagram 帐户,这就是本示例中登录未经过身份验证的原因。但正如您在下面看到的,代码仍然能够从登录 POST 接收带有 JSON 数据的 HTTP 200 响应。

GET / HTTP/1.1
Host: www.instagram.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36
HTTP/1.1 200 OK
Strict-Transport-Security: max-age=86400
Content-Language: en
Set-Cookie: sessionid=; expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/; HttpOnly; Domain=instagram.com
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Vary: Cookie, Accept-Language, Accept-Encoding
Pragma: no-cache
Cache-Control: private, no-cache, no-store, must-revalidate
Date: Tue, 21 Jun 2016 20:06:56 GMT
X-Frame-Options: SAMEORIGIN
Content-Type: text/html
Set-Cookie: csrftoken=<token>; expires=Tue, 20-Jun-2017 20:06:56 GMT; Max-Age=31449600; Path=/
Set-Cookie: mid=<value>; expires=Mon, 16-Jun-2036 20:06:56 GMT; Max-Age=630720000; Path=/
Connection: keep-alive
Content-Length: <HTML byte length>

<actual HTML bytes>
POST /accounts/login/ajax/ HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: <params byte length>
X-CSRFToken: <token>
X-Instagram-AJAX: 1
X-Requested-With: XMLHttpRequest
Host: www.instagram.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Referer: https://www.instagram.com/
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.76 Mobile Safari/537.36
Cookie: mid=<value>; csrftoken=<token>

username=<user>&password=<pass>
HTTP/1.1 200 OK
Strict-Transport-Security: max-age=86400
Content-Language: en
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Vary: Cookie, Accept-Language
Pragma: no-cache
Cache-Control: private, no-cache, no-store, must-revalidate
Date: Tue, 21 Jun 2016 20:06:57 GMT
Content-Type: application/json
Set-Cookie: csrftoken=<token>; expires=Tue, 20-Jun-2017 20:06:57 GMT; Max-Age=31449600; Path=/
Connection: close
Content-Length: <json byte length>

{"status": "ok", "authenticated": false, "user": "<user>"}

关于delphi - 如何在delphi10中使用IdHTTP登录Instagram网站,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37951677/

相关文章:

delphi - 可以使用 FinalBuilder 每天构建一个 fortran 项目(F77、F90 及更高版本)吗?

Delphi - JPEG 错误 #53

javascript - 如何阻止特定 Sharepoint 页面的身份验证

php - 在php中使用mysqli_connect通过http认证

laravel - 在用户登录页面后添加路由

delphi - Delphi 程序中的统计表

delphi - 在 Delphi XE2 中使用样式的字符串网格 - 滚动条不更新

json - Http获取json转化为字符串

Delphi:使用TidHTTPServer传输文件并监控单个请求的字节发送

Delphi - 使用 TIdMultipartFormDataStream idHTTP 上传文件