2009-05-30 7 views
62

Je suis relativement nouveau à l'utilisation de C#, et j'ai une application qui lit des parties du code source sur un site Web. Tout cela fonctionne mais le problème est que la page en question nécessite que l'utilisateur soit connecté pour accéder à ce code source. Qu'est-ce que mon programme a besoin d'un moyen de connecter initialement l'utilisateur sur le site Web. Après cela, je serai en mesure d'accéder et de lire le code source.Connectez-vous sur le site Web, via C#

Le site qui doit être connecté à est: mmoinn.com/index.do?PageModule=UsersLogin

J'ai cherché toute la journée sur la façon de le faire et a essayé des exemples, mais ont eu pas de chance.

Merci à l'avance

+0

Alors, je peux penser à un tas de façons de le faire ... Est-ce que Le programme C# demande le 'code' directement depuis le serveur via HTTP ou est-ce que vous vous retrouvez sur l'application du navigateur ou quoi? Un peu plus d'informations est nécessaire. –

+0

Le programme utilise WebClient.DownloadString ("URL") –

Répondre

95

Vous pouvez continuer à utiliser WebClient pour POST (au lieu de GET, qui est le HTTP verb que vous utilisez actuellement avec DownloadString), mais je pense que vous trouverez plus facile de travailler avec les classes (légèrement) de niveau inférieur WebRequest et WebResponse.

Il y a deux parties à cela: la première est de poster le formulaire de connexion, la seconde récupère l'entête "Set-cookie" et l'envoie au serveur en tant que "Cookie" avec votre requête GET. Le serveur utilisera ce cookie pour vous identifier à partir de maintenant (en supposant qu'il utilise une authentification basée sur les cookies dont je suis assez confiant car cette page renvoie un en-tête Set-cookie qui inclut "PHPSESSID").


Affectations à la forme de connexion

messages de formulaire sont faciles à simuler, il est juste un cas de formatage de vos données post comme suit:

field1=value1&field2=value2 

En utilisant WebRequest et le code I adapté de Scott Hanselman, voici comment vous POST former des données à votre formulaire de connexion:

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

Voici un exemple de ce que vous devriez voir dans l'en-tête Set-Cookie pour votre formulaire de connexion:

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

obtenir la page derrière le formulaire de connexion

Maintenant, vous pouvez effectuer votre GET demande à une page pour laquelle vous devez être connecté.

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:

Si vous voulez voir les résultats de la première POST, vous pouvez récupérer le code HTML, il est revenu avec:

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

Placez ce directement au-dessous cookieHeader = resp.Headers["Set-cookie"]; puis inspecter la chaîne contenue dans pageSource.

+0

Merci beaucoup pour la réponse détaillée; mais il y a encore une partie dont je ne suis pas sûr. Suis-je censé changer quelque chose concernant "Set -cookie", "Cookie", ou le "PHPSESSID" que vous avez posté? J'ai essayé simplement d'utiliser ce code dans un programme avec la saisie de mes informations, mais il ne semble pas être en train de me connecter (je suppose que je fous quelque chose avec les cookies). –

+0

Le code devrait être OK pour utiliser verbatim. Le serveur définit le cookie (dans Set-cookie) et le client (c'est vous) envoie le cookie en tant que cookie).La première chose à vérifier est que le premier POST vous connecte réellement, vous pouvez trouver le serveur attendu un autre champ dans votre formulaire POST (aussi étrange que cela puisse paraître, vous avez parfois besoin d'un champ vide avec le nom du bouton). J'ai mis à jour le post pour montrer comment afficher les résultats du POST. –

+0

Je ne suis pas sûr de ce que je faisais mal la première fois, mais ça marche maintenant! Merci beaucoup pour l'aide. –

30

Vous pouvez simplifier un peu les choses en créant une classe dérivée de WebClient, en remplaçant sa méthode GetWebRequest et en lui affectant un objet CookieContainer. Si vous définissez toujours la même instance CookieContainer, la gestion des cookies sera gérée automatiquement pour vous. Mais la seule façon d'obtenir HttpWebRequest avant d'être envoyé est d'hériter de WebClient et de surcharger cette méthode.

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

très bon code, mais ne fonctionne pas bien pour les pages ajax – Smith

+1

fonctionne très bien! D'autres solutions n'ont pas fonctionné pour mon site! merci – pila

+0

Lors du débogage, le cookie (rendu public) est toujours vide. Le site Web est sûr de donner des cookies sur les pages que je télécharge. – C4u

2

Parfois, il peut aider à éteindre AllowAutoRedirect et mettre la connexion au serveur POST et page GET demande le même agent utilisateur.

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

Matthew Brindley, votre code a travaillé très bon pour un certain site Web que je avais besoin (avec login), mais je devais changer pour HttpWebRequest et HttpWebResponse sinon je reçois un 404 Bad Request du serveur distant. Aussi je voudrais partager ma solution de contournement en utilisant votre code, et c'est que je l'ai essayé pour me connecter à un site basé sur moodle, mais cela n'a pas fonctionné à votre étape "OBTENIR la page derrière le formulaire de connexion" parce que quand avec succès POSTing le login, l'en-tête 'Set-Cookie' n'a rien retourné malgré d'autres sites Web.

Donc je pense que c'est là où nous avons besoin de stocker des cookies pour les prochaines demandes, alors j'ai ajouté ceci.


Pour la "Affectations à la forme de connexion" bloc de code:

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


Et à la "obtenir la page derrière le formulaire de connexion":

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


En faisant cela, laissez-moi Connectez-moi et obtenir le code source de la "page derrière login" (site web moodle) Je sais que c'est une utilisation vague du CookieContainer et HTTPCookies parce que nous pouvons demander d'abord est-il un ensemble de cookies précédemment enregistré avant d'envoyer la demande au serveur . Cela fonctionne sans problème de toute façon, mais voici une bonne information à lire sur WebRequest et WebResponse avec des exemples de projets et tutoriel:
Retrieving HTTP content in .NET
How to use HttpWebRequest and HttpWebResponse in .NET

Questions connexes