如何在delphi10中使用IdHTTP登录Instagram网站
How to login to Instagram website using IdHTTP in delphi10
我正在尝试使用 Delphi 中的 idhttp 登录 Instagram 网站。
我使用 google chrome 开发人员工具来获取数据,这是我迄今为止尝试过的方法..
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;
我现在手动获取访问令牌,只是为了测试代码。我得到 HTTP/1.1 403 Forbidden.
!
更新
这是cookie信息..
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 也不例外。
此外,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;
这是两个请求的结果 HTTP 对话框 1:
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 中的 idhttp 登录 Instagram 网站。 我使用 google chrome 开发人员工具来获取数据,这是我迄今为止尝试过的方法..
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;
我现在手动获取访问令牌,只是为了测试代码。我得到 HTTP/1.1 403 Forbidden.
!
更新
这是cookie信息..
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 也不例外。
此外,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;
这是两个请求的结果 HTTP 对话框 1:
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>"}