2011-12-22 16 views
7

mam bardzo trudny czas próby uwierzytelnienia do accounts.google.com używając WebClientC# WebClient logowanie do accounts.google.com

Używam C# WebClient obiektu, aby osiągnąć następujące.

jestem składania pól formularza do https://accounts.google.com/ServiceLoginAuth?service=oz

Oto POST Pola:

service=oz 
dsh=-8355435623354577691 
GALX=33xq1Ma_CKI 
timeStmp= 
secTok= 
[email protected] 
Passwd=password 
signIn=Sign in 
PersistentCookie=yes 
rmShown=1 

Teraz, gdy strona logowania ładunki przed przesłać dane, które zawiera następujące nagłówki:

Content-Type    text/html; charset=UTF-8 
Strict-Transport-Security max-age=2592000; includeSubDomains 
Set-Cookie     GAPS=1:QClFh_dKle5DhcdGwmU3m6FiPqPoqw:SqdLB2u4P2oGjt_x;Path=/;Expires=Sat, 21-Dec-2013 07:31:40 GMT;Secure;HttpOnly 
Cache-Control    no-cache, no-store 
Pragma      no-cache 
Expires      Mon, 01-Jan-1990 00:00:00 GMT 
X-Frame-Options    Deny 
X-Auto-Login    realm=com.google&args=service%3Doz%26continue%3Dhttps%253A%252F%252Faccounts.google.com%252FManageAccount 
Content-Encoding   gzip 
Transfer-Encoding   chunked 
Date      Thu, 22 Dec 2011 07:31:40 GMT 
X-Content-Type-Options  nosniff 
X-XSS-Protection   1; mode=block 
Server      GSE 

OK jak mogę teraz użyć klasy WebClient, aby uwzględnić te nagłówki?

Próbowałem , ale ma ograniczony efekt i zawsze zwraca stronę logowania.

Poniżej znajduje się klasa, z której korzystam. Doceniam każdą pomoc.


Pierwsze strony logowania

public void LoginPageRequest(Account acc) 
    { 

     var rparams = new RequestParams(); 
     rparams.URL = @"https://accounts.google.com/ServiceLoginAuth?service=oz"; 
     rparams.RequestName = "LoginPage"; 
     rparams.Account = acc; 

     webClient_.DownloadDataAsync(new Uri(rparams.URL), rparams); 
    } 

    void webClient__DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e) 
    { 
     RequestParams rparams = (RequestParams)e.UserState; 

     if (rparams.RequestName == "LoginPage") 
     { 
      ParseLoginRequest(e.Result, e.UserState); 
     } 
    } 

Teraz coraz pola formularza przy użyciu HtmlAgilityPack i dodawanie ich do kolekcji Parameters

public void ParseLoginRequest(byte[] data, object UserState) 
    { 
     RequestParams rparams = (RequestParams)UserState; 

     rparams.ClearParams(); 

     ASCIIEncoding encoder = new ASCIIEncoding(); 

     string html = encoder.GetString(data); 

     HtmlNode.ElementsFlags.Remove("form"); 

     HtmlDocument doc = new HtmlDocument(); 
     doc.LoadHtml(html); 

     HtmlNode form = doc.GetElementbyId("gaia_loginform"); 

     rparams.URL = form.GetAttributeValue("action", string.Empty); 
     rparams.RequestName = "LoginPost"; 

     var inputs = form.Descendants("input"); 
     foreach (var element in inputs) 
     { 
      string name = element.GetAttributeValue("name", "undefined"); 
      string value = element.GetAttributeValue("value", ""); 
      if (!name.Equals("undefined")) { 

       if (name.ToLower().Equals("email")) 
       { 
        value = rparams.Account.Email; 
       } 
       else if (name.ToLower().Equals("passwd")) 
       { 
        value = rparams.Account.Password; 
       } 

       rparams.AddParam(name,value); 
       Console.WriteLine(name + "-" + value); 
      } 
     } 

     webClient_.UploadValuesAsync(new Uri(rparams.URL),"POST", rparams.GetParams,rparams); 

Po opublikować dane otrzymuję strony logowania zamiast przekierowania lub sukces wiadomość.

Co robię źle?

Odpowiedz

4

Po krótkim zastanowieniu wygląda na to, że klasa WebClient nie jest najlepszym podejściem do tego konkretnego problemu.

Aby osiągnąć następujący cel, musiałem przejść o jeden poziom poniżej do WebRequest.

Dokonując WebRequest (HttpWebRequest) i stosując HttpWebResponse możliwe jest ustawienie CookieContainer

 webRequest_ = (HttpWebRequest)HttpWebRequest.Create(rparams.URL); 

     webRequest_.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"; 
     CookieContainer cookieJar = new CookieContainer(); 
     webRequest_.CookieContainer = cookieJar; 

     string html = string.Empty; 

     try 
     { 
      using (WebResponse response = webRequest_.GetResponse()) 
      { 
       using (var streamReader = new StreamReader(response.GetResponseStream())) 
       { 
        html = streamReader.ReadToEnd(); 
        ParseLoginRequest(html, response,cookieJar); 
       } 
      } 
     } 
     catch (WebException e) 
     { 
      using (WebResponse response = e.Response) 
      { 
       HttpWebResponse httpResponse = (HttpWebResponse)response; 
       Console.WriteLine("Error code: {0}", httpResponse.StatusCode); 
       using (var streamReader = new StreamReader(response.GetResponseStream())) 
        Console.WriteLine(html = streamReader.ReadToEnd()); 
      } 
     } 

a następnie przy podejmowaniu po użyciu tego samego Cookie pojemnik w następujący sposób

 webRequest_ = (HttpWebRequest)HttpWebRequest.Create(rparams.URL); 

     webRequest_.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"; 
     webRequest_.Method = "POST"; 
     webRequest_.ContentType = "application/x-www-form-urlencoded"; 
     webRequest_.CookieContainer = cookieJar; 

     var parameters = new StringBuilder(); 

     foreach (var key in rparams.Params) 
     { 
      parameters.AppendFormat("{0}={1}&",HttpUtility.UrlEncode(key.ToString()), 
       HttpUtility.UrlEncode(rparams.Params[key.ToString()])); 
     } 

     parameters.Length -= 1; 

     using (var writer = new StreamWriter(webRequest_.GetRequestStream())) 
     { 
      writer.Write(parameters.ToString()); 
     } 

     string html = string.Empty; 

     using (response = webRequest_.GetResponse()) 
     { 
      using (var streamReader = new StreamReader(response.GetResponseStream())) 
      { 
       html = streamReader.ReadToEnd(); 

      } 
     } 

Tak to działa, ten kod nie jest przeznaczony do użytku produkcyjnego i może/powinien być zoptymalizowany. Traktuj to jako przykład.

+0

Mogę to uruchomić, czy możesz wysłać przykładowy projekt? – Smith

3

To jest szybki przykład napisany w okienku odpowiedzi i nieprzetestowany. Prawdopodobnie będziesz musiał przeanalizować niektóre wartości z początkowego żądania dla niektórych wartości formularza, aby przejść do formularza danych. Wiele mojego kodu opiera się na tym typie procesu, chyba że musimy zeskrobać facebookowe strony typu talko, w którym to przypadku ajax sprawia, że ​​używamy innego podejścia.

using System; 
using System.Collections.Generic; 
using System.Collections.Specialized; 
using System.Linq; 
using System.Text; 

namespace GMailTest 
{ 
    class Program 
    { 
     private static NameValueCollection formData = new NameValueCollection(); 
     private static CookieAwareWebClient webClient = new CookieAwareWebClient(); 

     static void Main(string[] args) 
     { 
      formData.Clear(); 
      formData["service"] = "oz"; 
      formData["dsh"] = "-8355435623354577691"; 
      formData["GALX"] = "33xq1Ma_CKI"; 
      formData["timeStmp"] = ""; 
      formData["secTok"] = ""; 
      formData["Email"] = "[email protected]"; 
      formData["Passwd"] = "password"; 
      formData["signIn"] = "Sign in"; 
      formData["PersistentCookie"] = "yes"; 
      formData["rmShown"] = "1"; 

      byte[] responseBytes = webClient.UploadValues("https://accounts.google.com/ServiceLoginAuth?service=oz", "POST", formData); 
      string responseHTML = Encoding.UTF8.GetString(responseBytes); 
     } 
    } 

    public class CookieAwareWebClient : WebClient 
    { 
     public CookieAwareWebClient() : this(new CookieContainer()) 
     { } 

     public CookieAwareWebClient(CookieContainer c) 
     { 
      this.CookieContainer = c; 
      this.Headers.Add("User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5"); 
     } 

     public CookieContainer CookieContainer { get; set; } 

     protected override WebRequest GetWebRequest(Uri address) 
     { 
      WebRequest request = base.GetWebRequest(address); 
      if (request is HttpWebRequest) 
      { 
       (request as HttpWebRequest).CookieContainer = this.CookieContainer; 
      } 
      return request; 
     } 
    } 
} 
+1

Wygląda na to, że Rob zajmuje się tą samą branżą, co ja, chętnie skontaktuję się z Tobą, aby omówić niektóre aproki AJAX, o których wspomniałeś w tym poście. – Tim

+0

Wysłano ci zaproszenie do FB –