2012-03-06 31 views
5

Estoy intentando escribir código que se autenticará en el sitio web wallbase.cc. He mirado en lo que hace uso de herramientas de desarrollador Firfebug/Chrome y parece bastante fácil:Problemas al autenticar al sitio web desde el código

postal "usrname = $ USER & pase = $ PASS & nopass_email = Tipo + + en su dirección de correo + + y + presione + ingrese & nopass = 0 "a la página web" http://wallbase.cc/user/login ", almacene las cookies devueltas y úselas en todas las solicitudes futuras.

Aquí está mi código:

private CookieContainer _cookies = new CookieContainer(); 

    //...... 

    HttpPost("http://wallbase.cc/user/login", string.Format("usrname={0}&pass={1}&nopass_email=Type+in+your+e-mail+and+press+enter&nopass=0", Username, assword)); 

    //...... 


    private string HttpPost(string url, string parameters) 
    { 
     try 
     { 
      System.Net.WebRequest req = System.Net.WebRequest.Create(url); 
      //Add these, as we're doing a POST 
      req.ContentType = "application/x-www-form-urlencoded"; 
      req.Method = "POST"; 

      ((HttpWebRequest)req).Referer = "http://wallbase.cc/home/"; 
      ((HttpWebRequest)req).CookieContainer = _cookies; 

      //We need to count how many bytes we're sending. Post'ed Faked Forms should be name=value& 
      byte[] bytes = System.Text.Encoding.ASCII.GetBytes(parameters); 
      req.ContentLength = bytes.Length; 
      System.IO.Stream os = req.GetRequestStream(); 
      os.Write(bytes, 0, bytes.Length); //Push it out there 
      os.Close(); 

      //get response 
      using (System.Net.WebResponse resp = req.GetResponse()) 
      { 

       if (resp == null) return null; 
       using (Stream st = resp.GetResponseStream()) 
       { 
        System.IO.StreamReader sr = new System.IO.StreamReader(st); 
        return sr.ReadToEnd().Trim(); 
       } 
      } 
     } 
     catch (Exception) 
     { 
      return null; 
     } 
    } 

Después de llamar HttpPost con mis parámetros de conexión que se puede esperar todas las llamadas futuras utilizando este mismo método para ser autenticados (suponiendo un nombre de usuario/contraseña válidos). Obtengo una cookie de sesión en mi colección de cookies, pero por alguna razón no estoy autenticado. Recibo una cookie de sesión en mi colección de cookies independientemente de la página que visite, así que traté de cargar la página de inicio primero para obtener la cookie de sesión inicial y luego iniciar sesión, pero no hubo cambios.

Que yo sepa, esta versión de Python funciona: https://github.com/sevensins/Wallbase-Downloader/blob/master/wallbase.sh (línea 336)

¿Alguna idea sobre cómo conseguir que funcione la autenticación?

Actualización # 1
Cuando se utiliza un usuario/contraseña correcta emparejar la respuesta redirige automáticamente a la de referencia, pero cuando se recibe un par usuario/acceso incorrecto que no redirige y devuelve un mal par de usuario/pass. En base a esto, parece que la autenticación está ocurriendo, pero tal vez no se estén guardando todas las piezas clave de información.

Actualización # 2

estoy usando .NET 3.5. Cuando probé el código anterior en .NET 4, con la línea agregada de System.Net.ServicePointManager.Expect100Continue = false (que estaba en mi código, que no se muestra aquí) funciona, no es necesario realizar cambios. El problema parece provenir directamente de algún problema previo a la red 4.

+0

Debe asegurarse de cerrar/eliminar la 'respuesta' - o ponerla en un bloque' using() '. ¿Está reutilizando el mismo contenedor de cookies en solicitudes posteriores? – debracey

+0

@debracey: Estoy usando el mismo contenedor de cookies, el contenedor de cookies es una variable privada de nivel de clase que se reutiliza para cada HttpPost. Ajusté mi código para usar el uso de bloques y actualicé el código en mi pregunta, sin cambios. – Peter

Respuesta

6

Esto se basa en el código de uno de mis proyectos, así como el código encontrado de varias respuestas aquí en stackoverflow.

Primero tenemos que configurar un Cookie aware WebClient que va a usar HTML 1.0.

public class CookieAwareWebClient : WebClient 
{ 
    private CookieContainer cookie = new CookieContainer(); 

    protected override WebRequest GetWebRequest(Uri address) 
    { 
     HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address); 
     request.ProtocolVersion = HttpVersion.Version10; 
     if (request is HttpWebRequest) 
     { 
      (request as HttpWebRequest).CookieContainer = cookie; 
     } 
     return request; 
    } 
} 

A continuación se estableció el código que se encarga de la Authentication y, finalmente, carga el response.

var client = new CookieAwareWebClient(); 
client.UseDefaultCredentials = true; 
client.BaseAddress = @"http://wallbase.cc"; 

var loginData = new NameValueCollection(); 
loginData.Add("usrname", "test"); 
loginData.Add("pass", "123"); 
loginData.Add("nopass_email", "Type in your e-mail and press enter"); 
loginData.Add("nopass", "0"); 
var result = client.UploadValues(@"http://wallbase.cc/user/login", "POST", loginData); 

string response = System.Text.Encoding.UTF8.GetString(result); 

Podemos probar esto mediante el HTML Visualizer incorporado en Visual Studio durante su estancia en el modo de depuración y usarlo para confirmar que hemos sido capaces de authenticate y cargar la página de inicio que se hospedan authenticated.

Success

La clave aquí es la creación de un CookieContainer y utilizar HTTP 1.0, en lugar de 1.1. No estoy del todo seguro de por qué forzarlo a usar 1.0 le permite autenticar y cargar la página con éxito, pero parte de la solución se basa en esta respuesta. https://stackoverflow.com/a/10916014/408182

que utilizan Fiddler para asegurarse de que la respuesta enviada por el C# Client era el mismo que con mi navegador web Chrome. También me permite confirmar si el C# client se está redirigiendo correctamente. En este caso, podemos ver que con HTML 1.0 obtenemos el HTTP/1.0 302 Found y luego nos redirecciona a la página de inicio según lo previsto. Si cambiamos de nuevo a HTML 1.1 obtendremos un HTTP/1.1 417 Expectation Failed message en su lugar. Fiddler

Hay algo de información en este mensaje de error disponible en este hilo de stackoverflow. HTTP POST Returns Error: 417 "Expectation Failed."

Editar: Hack/Arreglo para .NET 3.5

He pasado mucho tiempo tratando de averiguar la diferencia entre 3.5 y 4.0, pero en serio no tienen ni idea. Parece que 3.5 está creando una nueva cookie después de la autenticación y la única forma que encontré alrededor de esto fue autenticar al usuario dos veces.

También tuve que hacer algunos cambios en el WebClient basados ​​en la información de esta publicación. http://dot-net-expertise.blogspot.fr/2009/10/cookiecontainer-domain-handling-bug-fix.html

public class CookieAwareWebClient : WebClient 
{ 
    public CookieContainer cookies = new CookieContainer(); 
    protected override WebRequest GetWebRequest(Uri address) 
    { 
     var request = base.GetWebRequest(address); 
     var httpRequest = request as HttpWebRequest; 
     if (httpRequest != null) 
     { 
      httpRequest.ProtocolVersion = HttpVersion.Version10; 
      httpRequest.CookieContainer = cookies; 

      var table = (Hashtable)cookies.GetType().InvokeMember("m_domainTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, cookies, new object[] { }); 
      var keys = new ArrayList(table.Keys); 
      foreach (var key in keys) 
      { 
       var newKey = (key as string).Substring(1); 
       table[newKey] = table[key]; 
      } 
     } 
     return request; 
    } 
} 

var client = new CookieAwareWebClient(); 

var loginData = new NameValueCollection(); 
loginData.Add("usrname", "test"); 
loginData.Add("pass", "123"); 
loginData.Add("nopass_email", "Type in your e-mail and press enter"); 
loginData.Add("nopass", "0"); 

// Hack: Authenticate the user twice! 
client.UploadValues(@"http://wallbase.cc/user/login", "POST", loginData); 
var result = client.UploadValues(@"http://wallbase.cc/user/login", "POST", loginData); 

string response = System.Text.Encoding.UTF8.GetString(result); 
+0

¿Cómo se comprobó que estaba funcionando? Cuando ejecuto este código, veo "¡Hola, Anónimo!" en la respuesta, y no estoy conectado. – Peter

+0

Sí, estoy recibiendo lo mismo y es por eso que actualicé mi respuesta antes. Actualizaré mi respuesta pronto. – eandersson

+0

@Peter Ok, actualizó la respuesta. Tuve un gran error tipográfico en el código 'username' =>' usrname'. Además, asegúrese de actualizar la función 'CookieAwareWebClient' cuando la actualice también. – eandersson

3

Es posible que tenga que añadir lo siguiente:

//get response 
using (System.Net.WebResponse resp = req.GetResponse()) 
{ 
    foreach (Cookie c in resp.Cookies) 
     _cookies.Add(c); 
    // Do other stuff with response.... 
} 

Otra cosa que puede que tenga que hacer es, si el servidor responde con un 302 (redirigir) la solicitud Web .Net seguirá automáticamente y en el proceso podría perder la cookie que está buscando. Puede desactivar este comportamiento con el siguiente código:

req.AllowAutoRedirect = false; 
+0

Cuando intento agregar manualmente las cookies, parece que ya están allí, o las que acaban de sobrescribir (de cualquier forma, el número de cookies permanece igual antes y después del agregado). Está haciendo una redirección y he probado el código con y sin el indicador AllowAutoRedirect en verdadero/falso, pero no cambia nada. – Peter

+0

Prueba a ejecutar fiddler (http://www.fiddler2.com/fiddler2/) mientras realizas la solicitud para ver si realmente se están configurando las cookies. Puede que tenga que indicarle a su código que use el proxy. Puede hacerlo llamando a 'req.Proxy = new WebProxy ("127.0.0.1", 8888);' – SynXsiS

2

La pitón se hace referencia utiliza una URL de referencia diferente (http://wallbase.cc/start/). También es seguido por otra publicación a (http://wallbase.cc/user/adult_confirm/1). Pruebe el otro referente y siga con este POST.

Creo que se está autenticando correctamente, pero que el sitio necesita más información/afirmaciones de usted antes de continuar.

+0

http://wallbase.cc/user/adult_confirm/1 se usa para confirmar que desea ver fondos de pantalla que no sean seguros para el tipo de trabajo. Si usa una herramienta como Fiddler o Chromes Developer View, verá que esta URL nunca se golpea durante el proceso de autenticación. Lo intentaré con la referencia alternativa, pero estoy bastante seguro de que usar/start/está desactualizado y de que ya lo he probado. – Peter

Cuestiones relacionadas