Melden Sie sich über C # auf der Website an

81

Ich bin relativ neu in der Verwendung von C # und habe eine Anwendung, die Teile des Quellcodes auf einer Website liest. Das alles funktioniert; Das Problem ist jedoch, dass für die betreffende Seite der Benutzer angemeldet sein muss, um auf diesen Quellcode zugreifen zu können. Was mein Programm benötigt, um den Benutzer zunächst auf der Website anzumelden - danach kann ich auf den Quellcode zugreifen und ihn lesen.

Die Website, auf der angemeldet sein muss, lautet: mmoinn.com/index.do?PageModule=UsersLogin

Ich habe den ganzen Tag danach gesucht und Beispiele ausprobiert, aber kein Glück gehabt.

Danke im Voraus

RyBolt
quelle
Ich kann mir also eine Reihe von Möglichkeiten vorstellen, dies zu tun ... Fordert das C # -Programm den 'Code' direkt vom Server über HTTP an oder huckepack auf die Browser-Anwendung oder was? Ein bisschen mehr Info wird benötigt.
Mitch Baker
Das Programm verwendet WebClient.DownloadString ("URL")

Antworten:

112

Sie können WebClient weiterhin für POST verwenden (anstelle von GET, dem HTTP-Verb, das Sie derzeit mit DownloadString verwenden), aber ich denke, Sie werden es einfacher finden, mit den (geringfügig) untergeordneten Klassen WebRequest und WebResponse zu arbeiten.

Dies besteht aus zwei Teilen: Der erste besteht darin, das Anmeldeformular zu veröffentlichen, der zweite darin, den "Set-Cookie" -Header wiederherzustellen und diesen zusammen mit Ihrer GET-Anfrage als "Cookie" an den Server zurückzusenden. Der Server wird dieses Cookie von nun an verwenden, um Sie zu identifizieren (vorausgesetzt, es verwendet eine Cookie-basierte Authentifizierung, von der ich ziemlich sicher bin, dass diese Seite einen Set-Cookie-Header zurückgibt, der "PHPSESSID" enthält).


POSTing zum Anmeldeformular

Formularbeiträge sind einfach zu simulieren. Sie müssen lediglich Ihre Beitragsdaten wie folgt formatieren:

field1=value1&field2=value2

Mit WebRequest und Code, den ich von Scott Hanselman angepasst habe , können Sie die folgenden Formulardaten in Ihr Anmeldeformular POSTEN :

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"];

Hier ist ein Beispiel dafür, was Sie im Set-Cookie-Header für Ihr Anmeldeformular sehen sollten:

PHPSESSID=c4812cffcf2c45e0357a5a93c137642e; path=/; domain=.mmoinn.com,wowmine_referer=directenter; path=/; domain=.mmoinn.com,lang=en; path=/;domain=.mmoinn.com,adt_usertype=other,adt_host=-

Die Seite hinter dem Anmeldeformular abrufen

Jetzt können Sie Ihre GET-Anforderung für eine Seite ausführen, für die Sie angemeldet sein müssen.

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

BEARBEITEN:

Wenn Sie die Ergebnisse des ersten POST anzeigen müssen, können Sie den zurückgegebenen HTML-Code wiederherstellen mit:

using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
    pageSource = sr.ReadToEnd();
}

Platzieren Sie diese direkt darunter cookieHeader = resp.Headers["Set-cookie"];und überprüfen Sie die in pageSource enthaltene Zeichenfolge.

Matt Brindley
quelle
Vielen Dank für die ausführliche Antwort; Aber es gibt noch einen Teil, bei dem ich mir nicht sicher bin. Soll ich etwas an "Set-cookie", "Cookie" oder der von Ihnen geposteten "PHPSESSID" ändern? Ich habe versucht, diesen Code einfach in einem Programm mit Eingabe meiner Informationen zu verwenden, aber es scheint mich nicht anzumelden (ich nehme an, ich vermassle etwas mit den Cookies).
Der Code sollte in Ordnung sein, um wörtlich verwendet zu werden. Der Server setzt das Cookie (in Set-Cookie) und der Client (das sind Sie) sendet das Cookie als Cookie zurück. Als Erstes müssen Sie überprüfen, ob der erste POST Sie tatsächlich anmeldet. Möglicherweise erwartet der Server ein anderes Feld in Ihrem Formular-POST (so seltsam es auch klingt, manchmal benötigen Sie ein leeres Feld mit dem Namen der Schaltfläche). Ich habe den Beitrag aktualisiert, um zu zeigen, wie die Ergebnisse des POST angezeigt werden.
Matt Brindley
Ich bin mir nicht sicher, was ich beim ersten Mal falsch gemacht habe, aber es funktioniert jetzt! Vielen Dank für die Hilfe.
1
Wie kann ich feststellen, ob sich der Benutzer erfolgreich authentifiziert hat?
Cyral
2
Ich weiß, wir sollten uns hier nicht bedanken, aber Mann, du hast meinen Arsch gerettet! +1
Owen James
39

Sie können die Dinge erheblich vereinfachen, indem Sie eine Klasse erstellen, die von WebClient abgeleitet ist, die GetWebRequest-Methode überschreiben und ein CookieContainer-Objekt darauf festlegen. Wenn Sie immer dieselbe CookieContainer-Instanz festlegen, wird die Cookie-Verwaltung automatisch für Sie durchgeführt.

Die einzige Möglichkeit, vor dem Senden auf die HttpWebRequest zuzugreifen, besteht darin, von WebClient zu erben und diese Methode zu überschreiben.

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");
Josh
quelle
Beim Debuggen ist das (öffentlich gemachte) Cookie immer leer. Die Website gibt auf jeden Fall Cookies auf den Seiten aus, die ich herunterlade.
C4d
Vielen Dank, nach mehreren Stunden der Suche nach einer Lösung funktioniert dies!
Essej
9

Matthew Brindley , Ihr Code hat für einige Websites, die ich benötigte (mit Login), sehr gut funktioniert, aber ich musste zu wechseln, HttpWebRequestund HttpWebResponseansonsten erhalte ich eine 404 Bad Request vom Remote-Server. Außerdem möchte ich meine Problemumgehung mit Ihrem Code teilen und habe versucht, mich auf einer auf Moodle basierenden Website anzumelden , aber es hat bei Ihrem Schritt " Abrufen der Seite hinter dem Anmeldeformular " nicht funktioniert, da beim erfolgreichen POSTEN des Login, der Header 'Set-Cookie'hat trotz anderer Websites nichts zurückgegeben.

Ich denke, hier müssen wir Cookies für die nächsten Anfragen speichern, also habe ich dies hinzugefügt.


Zum Codeblock " POSTing to the login form ":

var cookies = new CookieContainer();
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(formUrl);
req.CookieContainer = cookies;


Und zum " Abrufen der Seite hinter dem Anmeldeformular ":

HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create(getUrl);
getRequest.CookieContainer = new CookieContainer();
getRequest.CookieContainer.Add(resp.Cookies);
getRequest.Headers.Add("Cookie", cookieHeader);


Auf diese Weise kann ich mich anmelden und den Quellcode der "Seite hinter dem Login" (Website-basiertes Moodle) CookieContainerabrufen. Ich weiß, dass dies eine vage Verwendung von und HTTPCookies ist, da wir möglicherweise zuerst fragen, ob zuvor ein Satz von Cookies gespeichert wurde Senden der Anfrage an den Server. Dies funktioniert ohnehin problemlos, aber hier finden Sie gute Informationen zu WebRequestund WebResponsemit Beispielprojekten und Lernprogrammen:
Abrufen von HTTP-Inhalten in .NET
Verwendung von HttpWebRequest und HttpWebResponse in .NET

Warum so ernst
quelle
2

Manchmal kann es hilfreich sein AllowAutoRedirect, sowohl Anmelde- POSTals auch Seitenanforderungen für GETdenselben Benutzeragenten auszuschalten und festzulegen .

request.UserAgent = userAgent;
request.AllowAutoRedirect = false;
TN.
quelle