Jestem stosunkowo nowy w używaniu języka C # i mam aplikację, która odczytuje części kodu źródłowego w witrynie internetowej. To wszystko działa; ale problem polega na tym, że dana strona wymaga, aby użytkownik był zalogowany, aby uzyskać dostęp do tego kodu źródłowego. To, czego potrzebuje mój program, aby wstępnie zalogować użytkownika na stronie internetowej - po wykonaniu tej czynności będę mógł uzyskać dostęp i odczytać kod źródłowy.
Witryna, do której należy się zalogować, to: mmoinn.com/index.do?PageModule=UsersLogin
Cały dzień szukałem, jak to zrobić i próbowałem przykładów, ale nie miałem szczęścia.
Z góry dziękuję
c#
httpwebrequest
webclient
RyBolt
źródło
źródło
Odpowiedzi:
Możesz nadal używać WebClient do POST (zamiast GET, który jest czasownikiem HTTP , którego obecnie używasz z DownloadString), ale myślę, że łatwiej będzie Ci pracować z (nieco) niższymi klasami WebRequest i WebResponse.
Są to dwie części - pierwsza to wysłanie formularza logowania, druga to odzyskanie nagłówka „Set-cookie” i wysłanie go z powrotem na serwer jako „Cookie” wraz z żądaniem GET. Serwer będzie od tej pory używał tego pliku cookie do identyfikacji użytkownika (zakładając, że korzysta z uwierzytelniania opartego na plikach cookie, co, jestem całkiem pewien, że jest, ponieważ strona zwraca nagłówek Set-cookie, który zawiera „PHPSESSID”).
POST do formularza logowania
Posty w formularzach można łatwo symulować, wystarczy sformatować dane postów w następujący sposób:
Korzystając z WebRequest i kodu, który dostosowałem od Scotta Hanselmana , oto jak POST dane formularza do formularza logowania:
string formUrl = "http://www.mmoinn.com/index.do?PageModule=UsersAction&Action=UsersLogin"; // NOTE: This is the URL the form POSTs to, not the URL of the form (you can find this in the "action" attribute of the HTML's form tag 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ład tego, co powinieneś zobaczyć w nagłówku Set-cookie w formularzu logowania:
POBIERZ stronę za formularzem logowania
Teraz możesz wykonać żądanie GET na stronie, na którą musisz się zalogować.
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(); }
EDYTOWAĆ:
Jeśli chcesz wyświetlić wyniki pierwszego testu POST, możesz odzyskać zwrócony kod HTML za pomocą:
using (StreamReader sr = new StreamReader(resp.GetResponseStream())) { pageSource = sr.ReadToEnd(); }
Umieść to bezpośrednio poniżej,
cookieHeader = resp.Headers["Set-cookie"];
a następnie sprawdź ciąg przechowywany w pageSource.źródło
Możesz nieco uprościć sprawę, tworząc klasę wywodzącą się z WebClient, zastępując jej metodę GetWebRequest i ustawiając na niej obiekt CookieContainer. Jeśli zawsze ustawisz tę samą instancję CookieContainer, zarządzanie plikami cookie będzie obsługiwane automatycznie.
Ale jedynym sposobem uzyskania HttpWebRequest przed wysłaniem jest dziedziczenie z WebClient i zastąpienie tej metody.
public class CookieAwareWebClient : WebClient { private CookieContainer cookie = new CookieContainer(); protected override WebRequest GetWebRequest(Uri address) { WebRequest request = base.GetWebRequest(address); if (request is HttpWebRequest) { (request as HttpWebRequest).CookieContainer = cookie; } return request; } } var client = new CookieAwareWebClient(); client.BaseAddress = @"https://www.site.com/any/base/url/"; var loginData = new NameValueCollection(); loginData.Add("login", "YourLogin"); loginData.Add("password", "YourPassword"); client.UploadValues("login.php", "POST", loginData); //Now you are logged in and can request pages string htmlSource = client.DownloadString("index.php");
źródło
Matthew Brindley , Twój kod działał bardzo dobrze w przypadku jakiejś strony internetowej, której potrzebowałem (z logowaniem), ale musiałem przejść na
HttpWebRequest
iHttpWebResponse
inaczej otrzymuję 404 Bad Request z serwera zdalnego. Również chciałbym podzielić się moją obejścia przy użyciu kodu, a jest to, że próbowałem go do logowania na stronie internetowej w oparciu o Moodle , ale to nie działa w kroku „ Getting strony za formularza logowania ”, ponieważ kiedy pomyślnie księgowania login, nagłówek'Set-Cookie'
nic nie zwrócił, mimo że inne strony internetowe to robią.Myślę więc, że to miejsce, w którym musimy przechowywać pliki cookie dla następnych żądań, więc dodałem to.
Do bloku kodu „ POSTing do formularza logowania ”:
var cookies = new CookieContainer(); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(formUrl); req.CookieContainer = cookies;
Oraz do „ POBIERANIA strony za formularzem logowania ”:
HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create(getUrl); getRequest.CookieContainer = new CookieContainer(); getRequest.CookieContainer.Add(resp.Cookies); getRequest.Headers.Add("Cookie", cookieHeader);
Robiąc to, pozwól mi się zalogować i pobrać kod źródłowy "strony za logowaniem" (moodle oparty na witrynie) Wiem, że jest to niejasne użycie
CookieContainer
plików cookie i HTTPCookies ponieważ możemy najpierw zapytać, czy wcześniej został zapisany zestaw plików cookie wysłanie żądania do serwera. Działa to bez problemu i tak, ale tutaj jest dobry, aby przeczytać o informacjiWebRequest
iWebResponse
z przykładowych projektów i poradnik:Pobieranie zawartości HTTP w .NET
Jak używać HttpWebRequest i HttpWebResponse w .NET
źródło
Czasami może pomóc wyłączenie
AllowAutoRedirect
i ustawienie zarówno logowania, jakPOST
iGET
żądań strony dla tego samego klienta użytkownika.request.UserAgent = userAgent; request.AllowAutoRedirect = false;
źródło