web-dev-qa-db-fra.com

Connexion à un site Web à l'aide de C # par programme

Donc, j'ai parcouru le Web en essayant d'en savoir plus sur la façon de se connecter à des sites Web par programmation à l'aide de C #. Je ne veux pas utiliser de client Web. Je pense que je veux utiliser quelque chose comme HttpWebRequest et HttpWebResponse, mais je n'ai aucune idée du fonctionnement de ces classes.

Je suppose que je cherche quelqu'un pour expliquer comment ils fonctionnent et les étapes nécessaires pour se connecter avec succès, par exemple, WordPress, un compte de messagerie ou tout site qui nécessite que vous remplissiez un formulaire avec un nom d'utilisateur et un mot de passe.

Voici une de mes tentatives:

// Declare variables
        string url = textBoxGetSource.Text;
        string username = textBoxUsername.Text;
        string password = PasswordBoxPassword.Password;

        // Values for site login fields - username and password html ID's
        string loginUsernameID = textBoxUsernameID.Text;
        string loginPasswordID = textBoxPasswordID.Text;
        string loginSubmitID = textBoxSubmitID.Text;

        // Connection parameters
        string method = "POST";
        string contentType = @"application/x-www-form-urlencoded";
        string loginString = loginUsernameID + "=" + username + "&" + loginPasswordID + "=" + password + "&" + loginSubmitID;
        CookieContainer cookieJar = new CookieContainer();
        HttpWebRequest request;

        request = (HttpWebRequest)WebRequest.Create(url);
        request.CookieContainer = cookieJar;
        request.Method = method;
        request.ContentType = contentType;
        request.KeepAlive = true;
        using (Stream requestStream = request.GetRequestStream())
        using (StreamWriter writer = new StreamWriter(requestStream))
        {
            writer.Write(loginString, username, password);
        }

        using (var responseStream = request.GetResponse().GetResponseStream())
        using (var reader = new StreamReader(responseStream))
        {
            var result = reader.ReadToEnd();
            Console.WriteLine(result);
            richTextBoxSource.AppendText(result);
        }

        MessageBox.Show("Successfully logged in.");

Je ne sais pas si je suis sur la bonne voie ou pas. Je reviens finalement à l'écran de connexion du site que j'essaie. J'ai téléchargé Fiddler et j'ai pu glaner un peu d'informations sur les informations envoyées au serveur, mais je me sens complètement perdu. Si quelqu'un pouvait faire la lumière ici, je l'apprécierais grandement.

12
DGarrett01

La connexion par programme aux sites Web est difficile et étroitement liée à la façon dont le site met en œuvre sa procédure de connexion. La raison pour laquelle votre code ne fonctionne pas est que vous ne traitez pas de tout cela dans vos demandes/réponses.

Prenons fif.com par exemple. Lorsque vous saisissez un nom d'utilisateur et un mot de passe, la demande de publication suivante est envoyée:

POST https://fif.com/login?task=user.login HTTP/1.1
Host: fif.com
Connection: keep-alive
Content-Length: 114
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: https://fif.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.103 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: https://fif.com/login?return=...==
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8
Cookie: 34f8f7f621b2b411508c0fd39b2adbb2=gnsbq7hcm3c02aa4sb11h5c87f171mh3; __utma=175527093.69718440.1410315941.1410315941.1410315941.1; __utmb=175527093.12.10.1410315941; __utmc=175527093; __utmz=175527093.1410315941.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=175527093.|1=RegisteredUsers=Yes=1

username=...&password=...&return=aHR0cHM6Ly9maWYuY29tLw%3D%3D&9a9bd5b68a7a9e5c3b06ccd9b946ebf9=1

Remarquez les cookies (en particulier le premier, votre jeton de session). Notez la valeur de retour cryptée codée par l'URL envoyée. Si le serveur constate qu'ils sont manquants, il ne vous laissera pas vous connecter.

HTTP/1.1 400 Bad Request

Ou pire, une réponse de 200 d'une page de connexion avec un message d'erreur enterré quelque part à l'intérieur.

Mais supposons simplement que vous avez pu collecter toutes ces valeurs magiques et les transmettre dans un objet HttpWebRequest. Le site ne connaîtrait pas la différence. Et il pourrait répondre par quelque chose comme ça.

HTTP/1.1 303 See other
Server: nginx
Date: Wed, 10 Sep 2014 02:29:09 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Location: https://fif.com/

J'espère que vous vous attendiez à ça. Mais si vous êtes arrivé jusque-là, vous pouvez désormais envoyer par programmation des demandes au serveur avec votre jeton de session maintenant validé et récupérer le code HTML attendu.

GET https://fif.com/ HTTP/1.1
Host: fif.com
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.103 Safari/537.36
Referer: https://fif.com/login?return=aHR0cHM6Ly9maWYuY29tLw==
Accept-Encoding: gzip,deflate
Accept-Language: en-US,en;q=0.8
Cookie: 34f8f7f621b2b411508c0fd39b2adbb2=gnsbq7hcm3c02aa4sb11h5c87f171mh3; __utma=175527093.69718440.1410315941.1410315941.1410315941.1; __utmb=175527093.12.10.1410315941; __utmc=175527093; __utmz=175527093.1410315941.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmv=175527093.|1=RegisteredUsers=Yes=1

Et c'est tout pour fif.com - ce jonglage de cookies, jetons et redirections sera complètement différent pour un autre site. D'après mon expérience (avec ce site en particulier), vous avez trois options pour passer à travers le mur de connexion.

  1. Écrivez un script incroyablement compliqué et fragile pour danser autour des procédures du site
  2. Connectez-vous manuellement au site avec votre navigateur, saisissez les valeurs magiques et branchez-les dans vos objets de demande ou
  3. Créez un script pour automatiser Selenium pour le faire pour vous.

Le sélénium peut gérer tous les jonglages, et à la fin, vous pouvez retirer les cookies et répondre normalement à vos demandes. Voici un exemple pour fif:

//Run Selenium
ChromeDriver cd = new ChromeDriver(@"chromedriver_win32");
cd.Url = @"https://fif.com/login";
cd.Navigate();
IWebElement e = cd.FindElementById("username");
e.SendKeys("...");
e = cd.FindElementById("password");
e.SendKeys("...");
e = cd.FindElementByXPath(@"//*[@id=""main""]/div/div/div[2]/table/tbody/tr/td[1]/div/form/fieldset/table/tbody/tr[6]/td/button");
e.Click();

//Get the cookies
foreach(OpenQA.Selenium.Cookie c in cd.Manage().Cookies.AllCookies)
{
    string name = c.Name;
    string value = c.Value;
    cc.Add(new System.Net.Cookie(name,value,c.Path,c.Domain));
}

//Fire off the request
HttpWebRequest hwr = (HttpWebRequest) HttpWebRequest.Create("https://fif.com/components/com_fif/tools/capacity/values/");
hwr.CookieContainer = cc;
hwr.Method = "POST";
hwr.ContentType = "application/x-www-form-urlencoded";
StreamWriter swr = new StreamWriter(hwr.GetRequestStream());
swr.Write("feeds=35");
swr.Close();

WebResponse wr = hwr.GetResponse();
string s = new System.IO.StreamReader(wr.GetResponseStream()).ReadToEnd();
24
xavier

Commander this post. C'est une autre façon de le faire et vous n'avez pas besoin d'installer de package, mais cela pourrait être plus facile avec Selenium.

"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 trouverez il est plus facile de travailler avec les classes (légèrement) de niveau inférieur WebRequest et WebResponse.

Il y a deux parties: la première consiste à publier 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 que je suis assez sûr que c'est que cette page renvoie un en-tête Set-cookie qui comprend "PHPSESSID").


PUBLICATION sur le formulaire de connexion

Les publications de formulaire sont faciles à simuler, il s'agit simplement de mettre en forme vos données de publication comme suit:

field1=value1&field2=value2

En utilisant WebRequest et le code que j'ai adapté de Scott Hanselman , voici comment vous feriez POST form data à votre formulaire de connexion:

string formUrl = "http://www.mmoinn.com/index.do?PageModule=UsersAction&Action=UsersLogin";

REMARQUE: Il s'agit de l'URL vers laquelle le formulaire est POST, pas l'URL du formulaire (vous pouvez le trouver dans l'attribut "action" du formulaire HTML marque

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=/;

domaine = .mmoinn.com, lang = en; chemin = /; domaine = .mmoinn.com, adt_usertype = autre, adt_Host = -


OBTENIR la page derrière le formulaire de connexion

Vous pouvez maintenant effectuer votre demande 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();
}

MODIFIER:

Si vous avez besoin d'afficher les résultats du premier POST, vous pouvez récupérer le code HTML retourné avec:

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

Placez-le directement sous cookieHeader = resp.Headers["Set-cookie"];, puis inspectez la chaîne contenue dans pageSource. "

2
DFSFOT