web-dev-qa-db-fra.com

Connectez-vous au site Web, via C #

Je suis relativement nouveau à l’utilisation de C # et dispose d’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. Ce que mon programme a besoin d’un moyen de connecter initialement l’utilisateur au site Web. Après cela, je pourrai accéder au code source et le lire.

Le site Web devant être connecté est: mmoinn.com/index.do?PageModule=UsersLogin

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

Merci d'avance

70
Dillon

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

Cela comporte deux parties - la première consiste à publier le formulaire de connexion, la seconde consiste à récupérer l’en-tête "Set-cookie" et à le renvoyer au serveur sous forme de "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 un cookie, ce dont je suis assez convaincu, car cette page renvoie un en-tête Set-cookie incluant "PHPSESSID").


POST au formulaire de connexion

Les publications sur formulaire sont faciles à simuler. Il vous suffit de formater vos données de publication de la manière suivante:

field1=value1&field2=value2

En utilisant WebRequest et le code que j'ai adapté de Scott Hanselman , voici comment vous auriez POST données de formulaire pour 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=-

Obtient la page derrière le formulaire de connexion

Vous pouvez maintenant effectuer votre requête GET sur 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 d'afficher les résultats du premier POST, vous pouvez récupérer le code HTML renvoyé avec:

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

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

103
Matt Brindley

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 définissant 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 le seul moyen d'obtenir l'accès à HttpWebRequest avant son envoi est d'hériter de WebClient et de remplacer 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");
34
Josh

Matthew Brindley , votre code a très bien fonctionné pour certains sites Web dont j'avais besoin (avec un identifiant), mais je devais passer à HttpWebRequest et HttpWebResponse sinon je reçois un 404 Requête incorrecte du serveur distant. Aussi, j'aimerais partager ma solution de contournement en utilisant votre code. Je l’ai essayé de me connecter à un site Web basé sur moodle, mais cela n’a pas fonctionné à votre étape " Obtention de la page derrière le formulaire de connexion "car avec succès POSTing la connexion, l'en-tête 'Set-Cookie' n'a rien retourné malgré d'autres sites Web.

Je pense donc que nous devons stocker des cookies pour les prochaines demandes, alors j’ai ajouté ceci.


Pour le bloc de code " POST au formulaire de connexion ":

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


Et pour le " 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 Connectez-vous et obtenez le code source de la "page située derrière le login" (site Web moodle). Je sais que ceci est une utilisation vague du CookieContainer et HTTPCookies car nous pouvons demander d’abord si un jeu de cookies a été enregistré avant d’envoyer la demande au serveur. Cela fonctionne sans problème, mais voici une bonne information à lire sur WebRequest et WebResponse avec des exemples de projets et un tutoriel:
Récupération du contenu HTTP dans .NET
Comment utiliser HttpWebRequest et HttpWebResponse dans .NET

8
WhySoSerious

Parfois, il peut être utile de désactiver AllowAutoRedirect et de définir à la fois le login POST et la page GET pour demander le même agent utilisateur.

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