2011-12-22 26 views
7

tengo tiempo muy difícil intentar autenticar a accounts.google.com usando webclientC# WebClient entrada a accounts.google.com

estoy usando C# WebClient objeto de lograr siguiente.

que estoy presentando campos de formulario a https://accounts.google.com/ServiceLoginAuth?service=oz

Aquí es POST campos:

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

Ahora, cuando carga la página de inicio de sesión antes de presentar datos que tiene encabezados siguientes:

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 ahora, ¿cómo uso WebClient Class para incluir esos encabezados?

He intentado webClient_.Headers.Add(); pero tiene un efecto limitado y siempre devuelve la página de inicio de sesión.

A continuación se muestra una clase que yo uso. Agradecería cualquier ayuda.


Obtención de la página de inicio de sesión

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); 
     } 
    } 

ahora conseguir campos de formulario utilizando HtmlAgilityPack y añadirlas a la colección Parámetros

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); 

Después de publicar los datos que reciben la página de inicio de sesión en lugar de redirigir o el éxito mensaje.

¿Qué estoy haciendo mal?

Respuesta

4

Después de algunos cambios, parece que la clase WebClient no es el mejor enfoque para este problema en particular.

Para lograr el siguiente objetivo, tuve que saltar un nivel más abajo a WebRequest.

Al hacer WebRequest (HttpWebRequest) y el uso de HttpWebResponse es posible establecer 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()); 
      } 
     } 

y luego al hacer después utilizar el mismo contenedor de cookies en el siguiente manera

 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(); 

      } 
     } 

Así que esto funciona, este código no es para uso de producción y puede/debe ser optimizado. Trátelo solo como un ejemplo.

+0

puedo hacer que esto funcione, ¿puedes publicar un proyecto de muestra? – Smith

3

Este es un ejemplo rápido escrito en el panel de respuestas y no probado. Probablemente necesite analizar algunos valores de una solicitud inicial para que algunos valores de formulario ingresen a formData. Gran parte de mi código se basa en este tipo de proceso, a menos que necesitemos raspar los sitios de facebook spokeo, en cuyo caso el ajax nos hace usar un enfoque diferente.

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

Parece que Rob se involucra en la misma industria que yo, estaría dispuesto a ponerse en contacto con usted para analizar algunos enfoques de AJAX que ha mencionado en esta publicación – Tim

+0

Le enviamos una invitación a FB –