2014-09-10 17 views
5

Tak więc, przeszukałem sieć próbując dowiedzieć się więcej o tym, jak logicznie logować się do stron internetowych programowo przy użyciu C#. Nie chcę używać klienta WWW. Myślę, że chcę użyć czegoś takiego jak HttpWebRequest i HttpWebResponse, ale nie mam pojęcia jak te klasy działają.Logowanie do witryny przy użyciu C# programowo

Podejrzewam, że szukam kogoś, kto wyjaśni, jak działają i jakie kroki należy wykonać, aby pomyślnie zalogować się do, na przykład, WordPress, konta e-mail lub dowolnej witryny, która wymaga wypełnienia formularza z nazwą użytkownika i hasło.

Oto jeden z moich prób:

// Declare variables 
     string url = textBoxGetSource.Text; 
     string username = textBoxUsername.Text; 
     string password = PasswordBoxPassword.Password; 

     // Values for site login fields - username and password html ID's 
     string loginUsernameID = textBoxUsernameID.Text; 
     string loginPasswordID = textBoxPasswordID.Text; 
     string loginSubmitID = textBoxSubmitID.Text; 

     // Connection parameters 
     string method = "POST"; 
     string contentType = @"application/x-www-form-urlencoded"; 
     string loginString = loginUsernameID + "=" + username + "&" + loginPasswordID + "=" + password + "&" + loginSubmitID; 
     CookieContainer cookieJar = new CookieContainer(); 
     HttpWebRequest request; 

     request = (HttpWebRequest)WebRequest.Create(url); 
     request.CookieContainer = cookieJar; 
     request.Method = method; 
     request.ContentType = contentType; 
     request.KeepAlive = true; 
     using (Stream requestStream = request.GetRequestStream()) 
     using (StreamWriter writer = new StreamWriter(requestStream)) 
     { 
      writer.Write(loginString, username, password); 
     } 

     using (var responseStream = request.GetResponse().GetResponseStream()) 
     using (var reader = new StreamReader(responseStream)) 
     { 
      var result = reader.ReadToEnd(); 
      Console.WriteLine(result); 
      richTextBoxSource.AppendText(result); 
     } 

     MessageBox.Show("Successfully logged in."); 

Nie wiem, czy jestem na właściwej drodze, czy nie. W końcu wracam do ekranu logowania jakiejkolwiek strony, którą wypróbuję. Pobrałem Fiddlera i udało mi się zdobyć trochę informacji o tym, jakie informacje są wysyłane na serwer, ale czuję się kompletnie zagubiony. Gdyby ktokolwiek mógł rzucić tu trochę światła, byłbym bardzo wdzięczny.

+0

Możliwy duplikat [C# Zaloguj się do witryny za pośrednictwem programu] (http://stackoverflow.com/questions/930807/c-sharp-login-to-website-via-program) – RyBolt

Odpowiedz

17

Logowanie do stron internetowych programowo jest trudne i ściśle powiązane z tym, w jaki sposób witryna implementuje procedurę logowania. Powodem, dla którego twój kod nie działa, jest to, że nie zajmujesz się tym w swoich żądaniach/odpowiedziach.

Weźmy na przykład fif.com. Po wpisaniu nazwy użytkownika i hasła, co następuje prośba zostanie wysłana poczta:

POST https://fif.com/login?task=user.login HTTP/1.1 
Host: fif.com 
Connection: keep-alive 
Content-Length: 114 
Cache-Control: max-age=0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
Origin: https://fif.com 
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.103 Safari/537.36 
Content-Type: application/x-www-form-urlencoded 
Referer: https://fif.com/login?return=...== 
Accept-Encoding: gzip,deflate 
Accept-Language: en-US,en;q=0.8 
Cookie: 34f8f7f621b2b411508c0fd39b2adbb2=gnsbq7hcm3c02aa4sb11h5c87f171mh3; __utma=175527093.69718440.1410315941.1410315941.1410315941.1; __utmb=175527093.12.10.1410315941; __utmc=175527093; __utmz=175527093.1410315941.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=175527093.|1=RegisteredUsers=Yes=1 

username=...&password=...&return=aHR0cHM6Ly9maWYuY29tLw%3D%3D&9a9bd5b68a7a9e5c3b06ccd9b946ebf9=1 

Wskazówka ciasteczka (zwłaszcza pierwszy, sesja tokena). Zauważ, że wysyłana jest zakodowana wartość powrotna zakodowana w url. Jeśli serwer zauważy, że tego nie ma, nie pozwoli ci się zalogować.

HTTP/1.1 400 Bad Request 

Lub gorzej, 200 odpowiedzi strony logowania z komunikatem o błędzie ukrytym gdzieś w środku.

Ale udajmy, że udało ci się zebrać wszystkie te magiczne wartości i przekazać je do obiektu HttpWebRequest. Strona nie zna różnicy. I może odpowiedzieć z czymś takim.

HTTP/1.1 303 See other 
Server: nginx 
Date: Wed, 10 Sep 2014 02:29:09 GMT 
Content-Type: text/html; charset=utf-8 
Transfer-Encoding: chunked 
Connection: keep-alive 
Location: https://fif.com/ 

Mam nadzieję, że się tego spodziewałeś. Ale jeśli dotarłeś tak daleko, możesz teraz programowo odpalać żądania do serwera za pomocą sprawdzonego już tokena sesji i odzyskać oczekiwany kod HTML.

GET https://fif.com/ HTTP/1.1 
Host: fif.com 
Connection: keep-alive 
Cache-Control: max-age=0 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.103 Safari/537.36 
Referer: https://fif.com/login?return=aHR0cHM6Ly9maWYuY29tLw== 
Accept-Encoding: gzip,deflate 
Accept-Language: en-US,en;q=0.8 
Cookie: 34f8f7f621b2b411508c0fd39b2adbb2=gnsbq7hcm3c02aa4sb11h5c87f171mh3; __utma=175527093.69718440.1410315941.1410315941.1410315941.1; __utmb=175527093.12.10.1410315941; __utmc=175527093; __utmz=175527093.1410315941.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=175527093.|1=RegisteredUsers=Yes=1 

To wszystko dla fif.com - to żonglowanie ciasteczkami i tokenami oraz przekierowaniami będzie zupełnie inne dla innej witryny. Z mojego doświadczenia (zwłaszcza z tą witryną) masz trzy opcje przejścia przez ścianę logowania.

  1. Napisz niezwykle skomplikowaną i delikatną skrypt tańczyć wokół procedur witryny
  2. ręcznie zalogować się na stronę z przeglądarki, chwycić magiczne wartości i podłączyć je do swoich obiektów żądanie lub
  3. Utwórz skrypt zautomatyzować selenium, aby zrobić to za Ciebie.

Selen może poradzić sobie z żonglowaniem, a na koniec można wyciągnąć ciasteczka i wystrzelić normalnie.Oto przykład dla piątego:

//Run selenium 
ChromeDriver cd = new ChromeDriver(@"chromedriver_win32"); 
cd.Url = @"https://fif.com/login"; 
cd.Navigate(); 
IWebElement e = cd.FindElementById("username"); 
e.SendKeys("..."); 
e = cd.FindElementById("password"); 
e.SendKeys("..."); 
e = cd.FindElementByXPath(@"//*[@id=""main""]/div/div/div[2]/table/tbody/tr/td[1]/div/form/fieldset/table/tbody/tr[6]/td/button"); 
e.Click(); 

//Get the cookies 
foreach(OpenQA.Selenium.Cookie c in cd.Manage().Cookies.AllCookies) 
{ 
    string name = c.Name; 
    string value = c.Value; 
    cc.Add(new System.Net.Cookie(name,value,c.Path,c.Domain)); 
} 

//Fire off the request 
HttpWebRequest hwr = (HttpWebRequest) HttpWebRequest.Create("https://fif.com/components/com_fif/tools/capacity/values/"); 
hwr.CookieContainer = cc; 
hwr.Method = "POST"; 
hwr.ContentType = "application/x-www-form-urlencoded"; 
StreamWriter swr = new StreamWriter(hwr.GetRequestStream()); 
swr.Write("feeds=35"); 
swr.Close(); 

WebResponse wr = hwr.GetResponse(); 
string s = new System.IO.StreamReader(wr.GetResponseStream()).ReadToEnd(); 
+0

OK. Rozumiem, co masz na myśli. To ćwiczenie jest moim pierwszym krokiem w programowaniu sieciowym. Zwykle jestem zaznajomiony z łączeniem się z bazami danych, a to nic takiego. Wydaje się, że to więcej kłopotów niż jest warte. – DGarrett01

+1

Selen to wszystko, czego potrzebowałem. To spowodowało niesamowicie krótką pracę mojego problemu. – minnow

+3

Sprawdziło się świetnie, logując się do lazuru, aby zdobyć kredyty. Brakowało CookieContainer cc = new CookieContainer(); Chociaż – MrBeanzy

1

Zamówienie this post. Jest to inny sposób robienia tego i nie musisz instalować żadnego pakietu, chociaż może być łatwiej z Selenium.

„Można nadal używać WebClient na POST (zamiast GET, który jest HTTP verb obecnie używasz z DownloadString), ale Myślę, że łatwiej jest pracować z (nieznacznie) niższy poziom klas WebRequest i WebResponse

Istnieją dwie części do tego. - pierwsza to aby umieścić formularz logowania, drugi jest odzyskanie „Set-cookie” nagłówek i wysyłanie, że powrót do serwera jako "Cookie" wraz z żądaniem GET. Serwer użyje tego pliku cookie do identyfikacji użytkownika m teraz (zakładając, że używa on uwierzytelniania opartego na plikach cookie, co do którego jestem całkiem pewny, że strona zwraca nagłówek Set-cookie, który zawiera "PHPSESSID").


delegowania do formularza logowania

posty forma są łatwe do symulacji, to tylko przypadek formatowaniu danych post następująco:

field1=value1&field2=value2 

Korzystanie WebRequest i kodu I zaadaptowane z Scott Hanselman, oto , w jaki sposób POST utworzysz dane do formularza logowania:

string formUrl = "http://www.mmoinn.com/index.do?PageModule=UsersAction&Action=UsersLogin"; 

UWAGA: Jest to adres URL słupkami formularza do NOT, adres URL formularza (znajdziesz to w „akcji” atrybut formularza tag HTML za

string formParams = string.Format("email_address={0}&password={1}", "your email", "your password"); 
string cookieHeader; 
WebRequest req = WebRequest.Create(formUrl); 
req.ContentType = "application/x-www-form-urlencoded"; 
req.Method = "POST"; 
byte[] bytes = Encoding.ASCII.GetBytes(formParams); 
req.ContentLength = bytes.Length; 
using (Stream os = req.GetRequestStream()) 
{ 
    os.Write(bytes, 0, bytes.Length); 
} 
WebResponse resp = req.GetResponse(); 
cookieHeader = resp.Headers["Set-cookie"]; 

Oto przykładem tego, co powinieneś zobaczyć w nagłówku Set-Cookie na formularz logowania:

PHPSESSID=c4812cffcf2c45e0357a5a93c137642e; path=/; domain=.mmoinn.com,wowmine_referer=directenter; path=/; 

domenę = .mmoinn.com, lang = pl; path = /; domain = .mmoinn.com, adt_usertype = inny, adt_host = -


Uzyskiwanie strony za formularza logowania

Teraz można wykonać żądania GET do strony, która musisz być zalogowany.

string pageSource; 
string getUrl = "the url of the page behind the login"; 
WebRequest getRequest = WebRequest.Create(getUrl); 
getRequest.Headers.Add("Cookie", cookieHeader); 
WebResponse getResponse = getRequest.GetResponse(); 
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream())) 
{ 
    pageSource = sr.ReadToEnd(); 
} 

EDIT:

Jeśli chcesz zobaczyć wyniki pierwszego testu POST, można odzyskać HTML powrócił z:

using (StreamReader sr = new StreamReader(resp.GetResponseStream())) 
{ 
    pageSource = sr.ReadToEnd(); 
} 

Place to bezpośrednio poniżej cookieHeader = resp.Headers["Set-cookie"]; a następnie sprawdź ciąg przechowywany w pageSource. "

+1

Podczas gdy ten link może odpowiedzieć na pytanie, lepiej umieścić tutaj istotne części odpowiedzi i podać link do odniesienia. Odpowiedzi dotyczące linków mogą stać się nieprawidłowe, jeśli strona z linkami się zmieni. –

+0

@RaeenHashemi Tak, powinnam, dzięki! Wciąż nowicjusz tutaj .. – DFSFOT

+1

Po prostu kopiowanie-wklejanie całości cudzej odpowiedzi również nie jest odpowiednim zachowaniem (nawet jeśli link do niej). – nkjt

Powiązane problemy