2009-05-30 17 views
62

Sono relativamente nuovo nell'usare C# e ho un'applicazione che legge parti del codice sorgente su un sito web. Tutto funziona; ma il problema è che la pagina in questione richiede all'utente di accedere per accedere a questo codice sorgente. Quello che il mio programma ha bisogno di un modo per registrare inizialmente l'utente nel sito web, dopo che sarà stato fatto, potrò accedere e leggere il codice sorgente.Accesso al sito web, via C#

Il sito che deve essere effettuato l'accesso è: mmoinn.com/index.do?PageModule=UsersLogin

che ho cercato per tutta la giornata su come fare questo e esempi provato, ma ho avuto senza fortuna.

Grazie in anticipo

+0

Quindi, mi viene in mente un sacco di modi per fare questo ... fa il Il programma C# richiede il 'codice' direttamente dal server via HTTP o ti fa tornare indietro sull'applicazione del browser o cosa? Sono necessarie ulteriori informazioni. –

+0

Il programma utilizza WebClient.DownloadString ("URL") –

risposta

95

È possibile continuare a utilizzare WebClient su POST (anziché GET, che è lo HTTP verb attualmente utilizzato con DownloadString), ma penso che sarà più facile lavorare con le classi (leggermente) di livello inferiore WebRequest e WebResponse.

Ci sono due parti per questo: il primo è di inviare il modulo di accesso, il secondo è il ripristino dell'intestazione "Set-cookie" e l'invio al server come "Cookie" insieme alla richiesta GET. Il server utilizzerà questo cookie per identificarti da ora in poi (presumendo che stia utilizzando un'autenticazione basata su cookie che sono abbastanza fiducioso in quanto tale pagina restituisce un'intestazione Set-cookie che include "PHPSESSID").


postando il form di login

messaggi Form sono facili da simulare, è solo un caso di formattazione dei dati post come segue:

field1=value1&field2=value2 

Utilizzando WebRequest e il codice ho adattato da Scott Hanselman, ecco come inserire POST i dati nel modulo di accesso:

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

Ecco un esempio di ciò che si dovrebbe vedere nell'intestazione Set-cookie per il modulo di login:

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

Ottenere la pagina dietro il form di login

Ora è possibile eseguire la GET richiesta per una pagina per cui è necessario accedere.

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

EDIT:

Se è necessario visualizzare i risultati del primo post, è possibile recuperare il codice HTML è tornato con:

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

Luogo questo direttamente sotto cookieHeader = resp.Headers["Set-cookie"]; e poi ispezionare la stringa contenuta in pageSource.

+0

Grazie mille per la risposta dettagliata; ma c'è ancora una parte di cui non sono sicuro. Dovrei cambiare qualcosa riguardo a "Set -cookie", "Cookie" o al "PHPSESSID" che hai postato? Ho provato semplicemente ad usare quel codice in un programma con l'inserimento delle mie informazioni, ma non sembra che mi stia registrando (presumo che stia facendo un casino con i cookie). –

+0

Il codice dovrebbe essere OK per usare testualmente. Il server imposta il cookie (in Set-cookie) e il client (che sei tu) invia il cookie come cookie). La prima cosa da verificare è che il primo POST ti acceda effettivamente, potresti scoprire che il server si aspetta un altro campo nel tuo modulo POST (per quanto strano possa sembrare, a volte hai bisogno di un campo vuoto con il nome del pulsante). Ho aggiornato il post per mostrare come visualizzare i risultati del POST. –

+0

Non sono sicuro di cosa stavo facendo male la prima volta, ma ora funziona! Grazie mille per l'aiuto. –

30

È possibile semplificare un po 'le cose creando una classe che deriva da WebClient, sovrascrivendo il suo metodo GetWebRequest e impostando un oggetto CookieContainer su di esso. Se imposti sempre la stessa istanza di CookieContainer, la gestione dei cookie verrà gestita automaticamente per te.

Tuttavia, l'unico modo per ottenere HttpWebRequest prima che venga inviato è ereditare da WebClient e sovrascrivere tale metodo.

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"); 
+0

codice molto buono, ma non funziona bene per le pagine Ajax – Smith

+1

funziona bene! altre soluzioni non hanno funzionato per il mio sito! grazie – pila

+0

Durante il debug, il cookie (reso pubblico) è sempre vuoto. Il sito web offre sicuramente cookies sulle pagine che sto scaricando. – C4u

2

A volte, può aiutare a spegnere AllowAutoRedirect e impostazione sia login POST e pagina GET richieste lo stesso agente utente.

request.UserAgent = userAgent; 
request.AllowAutoRedirect = false; 
6

Matthew Brindley, il codice ha funzionato molto bene per qualche sito che mi serviva (con login), ma avevo bisogno di cambiare per HttpWebRequest e HttpWebResponse altrimenti ho un 404 Bad Request dal server remoto. Vorrei anche condividere la mia soluzione alternativa usando il tuo codice, ed è che l'ho provato ad accedere a un sito web basato su moodle, ma non ha funzionato al tuo passo "GETting la pagina dietro il modulo di login" perché in caso di esito positivo del login POSTing, l'intestazione 'Set-Cookie' non ha restituito nulla nonostante altri siti Web lo facciano.

Quindi penso che questo dove abbiamo bisogno di memorizzare i cookie per le prossime richieste, così ho aggiunto questo.


Alla "postando il form di login" blocco di codice:

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


e al "Ottenere la pagina dietro il form di login":

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


In questo modo, mi consente di accedere a Accedi a e ottenere il codice sorgente della "pagina dietro l'accesso" (moodle basato sul sito Web) So che questo è un uso vago di CookieContainer e HTTPCookies perché potremmo chiedere prima c'è un precedente set di cookie salvati prima di inviare la richiesta al server . Questo funziona senza problemi in ogni caso, ma qui è un buon informazioni di leggere su WebRequest e WebResponse con progetti di esempio e tutorial:
Retrieving HTTP content in .NET
How to use HttpWebRequest and HttpWebResponse in .NET

Problemi correlati