84 votes

Connexion au site web, via C#

Je suis relativement novice dans l'utilisation de C#, et j'ai une application qui lit des parties du code source d'un site web. Tout cela fonctionne, mais le problème est que la page en question exige que l'utilisateur soit connecté pour accéder à ce code source. Ce dont mon programme a besoin, c'est d'un moyen de connecter initialement l'utilisateur au site web - une fois que ce sera fait, je pourrai accéder au code source et le lire.

Le site web sur lequel il faut se connecter est le suivant : mmoinn.com/index.do?PageModule=UsersLogin

J'ai cherché toute la journée comment faire et j'ai essayé des exemples, mais je n'ai pas eu de chance.

Merci d'avance

116voto

Matthew Brindley Points 5240

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

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


POSTing vers le formulaire de connexion

Les formulaires de posts sont faciles à simuler, il suffit de formater les données de votre post comme suit :

field1=value1&field2=value2

Utilisation de WebRequest et d'un code que j'ai adapté à partir de Scott Hanselman Voici comment POSTER les données du formulaire dans 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 de 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

Vous pouvez maintenant effectuer votre requête GET vers 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 avez besoin de voir les résultats du premier POST, vous pouvez récupérer le code HTML qu'il a renvoyé :

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

Placez ceci directement en dessous de cookieHeader = resp.Headers["Set-cookie"]; puis inspecte la chaîne de caractères contenue dans pageSource.

40voto

Josh Points 38617

Vous pouvez simplifier les choses en créant une classe dérivée de WebClient, en surchargeant sa méthode GetWebRequest et en lui attribuant un objet CookieContainer. Si vous définissez toujours la même instance de CookieContainer, la gestion des cookies sera automatiquement prise en charge.

Mais le seul moyen d'accéder au HttpWebRequest avant qu'il ne soit 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");

9voto

WhySoSerious Points 560

Matthew Brindley Votre code a très bien fonctionné pour un site web dont j'avais besoin (avec login), mais j'ai eu besoin de changer en HttpWebRequest y HttpWebResponse sinon j'obtiens un 404 Mauvaise demande du serveur distant. J'aimerais également vous faire part de la solution que j'ai trouvée en utilisant votre code, à savoir que j'ai essayé de me connecter à un serveur de site web basé sur moodle mais cela n'a pas fonctionné à votre étape " Obtenir la page derrière le formulaire de connexion "car lorsqu'elle est réussie, la POSTing le login, l'en-tête 'Set-Cookie' n'a rien retourné, contrairement à d'autres sites web.

Je pense que c'est ici que nous devons stocker les cookies pour les prochaines requêtes, j'ai donc ajouté ceci.

Au " POSTing vers le formulaire de connexion "Bloc de code :

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

Et au " 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);

Cela me permet Me connecter et obtenir le code source de la "page derrière le login" (site web basé sur moodle) Je sais qu'il s'agit d'une utilisation vague de la fonction CookieContainer et HTTPCookies parce que nous pouvons d'abord demander s'il existe un ensemble de cookies sauvegardés avant d'envoyer la requête au serveur. Cela fonctionne sans problème de toute façon, mais voici une bonne information à ce sujet WebRequest y WebResponse avec des exemples de projets et un tutoriel :
Récupération du contenu HTTP en .NET
Comment utiliser HttpWebRequest et HttpWebResponse en .NET

3voto

Magnus Points 15064

Vous pouvez toujours utiliser la fonction Test web Watin cadre.

2voto

TN. Points 3450

Parfois, il peut être utile d'éteindre AllowAutoRedirect et en définissant à la fois le login POST et la page GET demande le même agent utilisateur.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X