2012-03-06 18 views
5

Próbuję napisać kod, który uwierzytelni się na stronie wallbase.cc. Mam spojrzał na to, co jest za pomocą narzędzi Firfebug/Chrome Developer i wydaje się dość proste:Problemy z uwierzytelnianiem na stronie z kodu

post „usrname = $ USER & pass = $ PASS & nopass_email = Typ + w + your + e-mail + i + naciśnij + wprowadź & nopass = 0 "do strony" http://wallbase.cc/user/login ", przechowuj zwrócone pliki cookie i używaj ich we wszystkich przyszłych zamówieniach.

Oto mój kod:

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

Po wywołaniu HttpPost z moich parametrów logowania spodziewałbym wszystkie przyszłe połączenia za pomocą tej samej metody, aby być uwierzytelniony (zakładając poprawną nazwę użytkownika/hasło). Dostaję plik cookie sesji w mojej kolekcji plików cookie, ale z jakiegoś powodu nie jestem uwierzytelniony. Dostaję plik cookie sesji w zbiorze plików cookie, niezależnie od tego, którą stronę odwiedzę, dlatego próbowałem najpierw załadować stronę główną, aby uzyskać plik cookie sesji początkowej, a następnie zalogować się, ale nie było żadnych zmian.

Według mojej wiedzy ta wersja Python działa: https://github.com/sevensins/Wallbase-Downloader/blob/master/wallbase.sh (linia 336)

pomysłów, w jaki sposób dostać uwierzytelniania działa?

Aktualizacja # 1
Podczas korzystania prawidłowe użytkownik/hasło powiązać odpowiedź automatycznie przekierowuje do polecający ale po odebraniu niepoprawne Użytkownik/hasło para nie przekierować i zwraca złe użytkownik/hasło parę. Na tej podstawie wydaje się, że uwierzytelnianie się dzieje, ale może nie wszystkie kluczowe informacje są zapisywane?

Aktualizacja # 2

Używam .NET 3.5. Kiedy wypróbowałem powyższy kod w .NET 4, z dodaną linią System.Net.ServicePointManager.Expect100Continue = false (która była w moim kodzie, właśnie nie pokazana tutaj) to działa, bez zmian koniecznych. Problem wydaje się wynikać bezpośrednio z niektórych problemów z pre-Net4.

+0

Musisz się upewnić, że zamknąłeś/wyrzuciłeś 'response' - lub umieściłeś go w bloku' using() '. Czy korzystasz ponownie z tego samego kontenera z ciasteczkami na kolejnych prośbach? – debracey

+0

@debracey: Używam tego samego kontenera cookie, kontener cookie to prywatna zmienna poziomu klasy, która jest ponownie używana dla każdego HttpPost. Poprawiłem swój kod, aby używać bloków i zaktualizowałem kod w moim pytaniu, bez zmian. – Peter

Odpowiedz

6

ta opiera się na kodzie z jednego z moich projektów, a także kodu znalezionego tutaj z różnych odpowiedzi na stackoverflow.

Najpierw musimy skonfigurować Cookie aware WebClient, który będzie używał 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; 
    } 
} 

Następnie należy ustawić kod, który obsługuje Authentication i wreszcie ładuje 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); 

Możemy spróbować z pomocą HTML Visualizer wbudowana w Visual Studio podczas pobytu w trybie debugowania i używać, aby potwierdzić, że udało nam się authenticate i załadować stronę domu podczas pobytu authenticated.

Success

Kluczem jest tu założyć CookieContainer i używać HTTP 1.0 zamiast 1.1. Nie jestem do końca pewien, dlaczego zmuszanie go do używania 1.0 pozwala na uwierzytelnienie i załadowanie strony z powodzeniem, ale część rozwiązania opiera się na tej odpowiedzi. https://stackoverflow.com/a/10916014/408182

użyłem Fiddler, aby upewnić się, że odpowiedź wysłana przez C# Client była taka sama jak w przeglądarce internetowej Chrome. Pozwala mi to również sprawdzić, czy kod C# client jest poprawnie przekierowywany. W tym przypadku widzimy, że z HTML 1.0 otrzymujemy HTTP/1.0 302 Found, a następnie przekierowujemy nas do strony głównej zgodnie z przeznaczeniem. Jeśli przełożymy się ponownie na HTML 1.1, otrzymamy zamiast tego HTTP/1.1 417 Expectation Failed message. Fiddler

Istnieje kilka informacji na temat tego komunikatu o błędzie dostępnych w tym wątku stackoverflow. HTTP POST Returns Error: 417 "Expectation Failed."

Edit: Hack/Fix dla .NET 3.5

spędziłem dużo czasu próbuje dowiedzieć się różnicę pomiędzy 3,5 i 4,0, ale poważnie nie mają pojęcia. Wygląda na to, że 3.5 tworzy nowy plik cookie po uwierzytelnieniu, a jedyny sposób, jaki znalazłem, polegał na dwukrotnym uwierzytelnianiu użytkownika.

Musiałem również wprowadzić pewne zmiany w WebClient na podstawie informacji z tego postu. 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

Jak zweryfikowałeś, że działa? Kiedy uruchamiam ten kod, widzę "Hej anonimowy!" w odpowiedzi i nie jestem zalogowany. – Peter

+0

Tak, otrzymuję to samo i dlatego zaktualizowałem swoją odpowiedź wcześniej. Niedługo zaktualizuję swoją odpowiedź. – eandersson

+0

@Peter Ok, zaktualizował odpowiedź. Miałem poważną literówkę w kodzie 'username' =>' usrname'. Ponadto, zaktualizuj również funkcję 'CookieAwareWebClient'. – eandersson

3

może trzeba dodać:

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

Inną rzeczą, którą można zrobić to, czy serwer odpowiada 302 (przekierowanie) wniosek internetowej .Net automatycznie po nim oraz w proces, w którym możesz stracić plik cookie, którego szukasz. Można wyłączyć to zachowanie za pomocą następującego kodu:

req.AllowAutoRedirect = false; 
+0

Kiedy próbuję ręcznie dodawać pliki cookie, wygląda na to, że już tam są, lub te, które zostały po prostu nadpisane (w ten sposób licznik plików cookie pozostaje taki sam przed dodaniem i po dodaniu). Robi przekierowanie, a ja wypróbowałem kod z flagą AllowAutoRedirect i bez niej na true/false, ale nic nie zmienia. – Peter

+0

Spróbuj uruchomić program fiddler (http://www.fiddler2.com/fiddler2/), wysyłając żądanie, aby sprawdzić, czy pliki cookie są rzeczywiście ustawione. Być może będziesz musiał powiedzieć swojemu kodowi, aby skorzystał z serwera proxy. Możesz to zrobić, wywołując "req.Proxy = new WebProxy (" 127.0.0.1 ", 8888); ' – SynXsiS

2

Python odwołać używa innego skierowania (http://wallbase.cc/start/). Następnie następuje kolejny post (http://wallbase.cc/user/adult_confirm/1). Wypróbuj inne strony odsyłające i obserwuj z tym POST.

Myślę, że prawidłowo uwierzytelniasz, ale strona potrzebuje więcej informacji/zapewnień od Ciebie, zanim przejdziesz dalej.

+0

http://wallbase.cc/user/adult_confirm/1 służy do potwierdzenia, że ​​chcesz zobaczyć tapety inne niż bezpieczne dla typu pracy. Jeśli używasz narzędzia, takiego jak widok programisty Fiddler lub Chromes, zobaczysz, że ten adres URL nigdy nie zostanie trafiony podczas procesu uwierzytelniania. Spróbuję go z alternatywnym stroną odsyłającą, ale jestem pewien, że użycie/start/jest nieaktualne i że już go wypróbowałem. – Peter