web-dev-qa-db-fra.com

C # - HttpWebRequest POST (Connexion à Facebook)

J'essaie de me connecter à Facebook dans mon programme et d'analyser certaines informations à partir de là (comme le nom, la photo de profil, etc.).

Je suis redirigé vers la page principale de Facebook chaque fois que j'exécute le code ci-dessous.

string email = "email";
string pw = "pw";
string PostData = String.Format("email={0}&pass={1}", email, pw);

CookieContainer cookieContainer = new CookieContainer();

HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("");
req.CookieContainer = cookieContainer;
req.Method = "POST";
req.ContentLength = PostData.Length;
req.ContentType = "application/x-www-form-urlencoded";
req.AllowAutoRedirect = true;
req.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";

ASCIIEncoding encoding = new ASCIIEncoding();
byte[] loginDataBytes = encoding.GetBytes(PostData);
req.ContentLength = loginDataBytes.Length;
Stream stream = req.GetRequestStream();
stream.Write(loginDataBytes, 0, loginDataBytes.Length);

HttpWebResponse webResp = (HttpWebResponse)req.GetResponse();

Stream datastream = webResp.GetResponseStream();
StreamReader reader = new StreamReader(datastream);
webBrowser1.DocumentText = reader.ReadToEnd();

foreach (Cookie cookies in webResp.Cookies)
{
    MessageBox.Show(cookies.Name + "   " + cookies.Value);
}

Qu'est-ce que je fais mal ici? Toute aide serait appréciée, merci beaucoup! :)

edit: J'ai découvert comment le faire peu de temps après avoir posté.

Facebook envoie un cookie à chaque fois que vous le visitez pour voir si vous avez activé les cookies, ce que j'ai fait a été d'envoyer une demande à la page de connexion de Facebook pour obtenir les cookies, puis en envoyer une autre avec les données POST Cela a fonctionné de cette façon et je me suis connecté avec succès.

Merci quand même! :)

19
user1086902

Je suis heureux que vous ayez trouvé votre réponse, j'ai pu me connecter à Facebook en utilisant HttpWebRequest aussi, comme vous l'avez dit .. Voici une solution de contournement acceptable:

Première demande : Obtenez les cookies.

 CookieCollection cookies = new CookieCollection();
 HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://www.facebook.com); 
 request.CookieContainer = new CookieContainer();
 request.CookieContainer.Add(cookies);
 //Get the response from the server and save the cookies from the first request..
 HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 cookies = response.Cookies;

Deuxième demande : POST les données du formulaire et récupérer les cookies de la première demande. .

 string getUrl = "https://www.facebook.com/login.php?login_attempt=1";
 string postData = String.Format("email={0}&pass={1}", "value1", "value2");
 HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create(getUrl);
 getRequest.CookieContainer = new CookieContainer();
 getRequest.CookieContainer.Add(cookies); //recover cookies First request
 getRequest.Method = WebRequestMethods.Http.Post;
 getRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
 getRequest.AllowWriteStreamBuffering = true;
 getRequest.ProtocolVersion = HttpVersion.Version11;
 getRequest.AllowAutoRedirect = true;
 getRequest.ContentType = "application/x-www-form-urlencoded";

 byte[] byteArray = Encoding.ASCII.GetBytes(postData);
 getRequest.ContentLength = byteArray.Length;   
 Stream newStream = getRequest.GetRequestStream(); //open connection
 newStream.Write(byteArray, 0, byteArray.Length); // Send the data.
 newStream.Close();

 HttpWebResponse getResponse = (HttpWebResponse)getRequest.GetResponse();
 using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
 {
   string sourceCode = sr.ReadToEnd();               
 } 

C'est l'une des nombreuses façons qui fonctionne avec HttpWebRequest, également si vous préférez utiliser WebBrowser, cela fonctionne de la manière suivante:

webBrowser1.Navigate("https://www.facebook.com/login.php?login_attempt=1", "",byteArray, "Content-Type: application/x-www-form-urlencoded");

Ce que je viens de réaliser, c'est que cela ne fonctionne pas avec le InternetSetCookie peut-être parce que les cookies renvoyés de Facebook ont ​​l'attribut "HttpOnly" (vrai), et il ne peut pas être accessible par un script côté client .

34
WhySoSerious

Parfois, il est plus facile d'utiliser un navigateur Web et vous pouvez exécuter ce navigateur caché en arrière-plan. Plus tard, vous pouvez obtenir le code HTML interne ou peut-être télécharger une image. Tout ce que vous devez faire. Voici un exemple d'utilisation de formulaires Windows.

Créez une nouvelle application de formulaires gagnants, ajoutez un bouton et collez ce code à l'intérieur. n'ajoutez rien d'autre ça devrait marcher ...

private void button1_Click(object sender, EventArgs e)
{
    string email = "Your email";
    string password = "your password";

    // create a new browser
    WebBrowser w = new WebBrowser();
    w.Dock = DockStyle.Fill;
    this.Controls.Add(w); // you may add the controll to your windows forms if  you want to see what is going on
    // latter you may not chose to add the browser or you can even set it to invisible... 


    // navigate to facebook
    w.Navigate(@"http://www.facebook.com/");

    // wait a little
    for (int i = 0; i < 100; i++)
    {
        System.Threading.Thread.Sleep(10);
        System.Windows.Forms.Application.DoEvents();
    }


    HtmlElement temp=null;

    // while we find an element by id named email
    while (temp == null)
    {
        temp = w.Document.GetElementById("email");
        System.Threading.Thread.Sleep(10);
        System.Windows.Forms.Application.DoEvents();
    }

    // once we find it place the value
    temp.SetAttribute("value", email);


    temp = null;
    // wiat till element with id pass exists
    while (temp == null)
    {
        temp = w.Document.GetElementById("pass");
        System.Threading.Thread.Sleep(10);
        System.Windows.Forms.Application.DoEvents();
    }
    // once it exist set it value equal to passowrd
    temp.SetAttribute("value", password);

    // if you already found the last fields the button should also be there...

    var inputs = w.Document.GetElementsByTagName("input");

    int counter = 0;
    bool enableClick = false;

    // iterate through all the inputs in the document
    foreach (HtmlElement btn in inputs)
    {

        try
        {
            var att = btn.GetAttribute("tabindex");
            var name = btn.GetAttribute("id");

            if (enableClick)// button to submit always has a differnt id. it should be after password textbox
            {
                btn.InvokeMember("click");
                counter++;
            }

            if (name.ToUpper().Contains("PASS") || att=="4") 
            {
                enableClick = true;  // button should be next to the password input                    
            }

            // try a max of 5 times
            if (counter > 5)
                break;
        }
        catch
        {

        }
    }
}
4
Tono Nam