Ho un caso con una semplice applicazione che sfoglia il sito di XenForo Forum, preleva i cookie e invia ulteriormente i dati post per accedere e recuperare alcune informazioni disponibili solo per gli utenti registrati.
Sono in grado di recuperare con successo i cookie e verificare di aver effettuato correttamente il login la prima volta, ma non riesco a rimanere loggato quando provo a "navigare" ulteriormente quando provo a riutilizzare gli stessi cookie.
Ecco cosa ho ottenuto finora:
public MainWindow()
{
InitializeComponent();
if (IsLoggedIn())
{
GetPage("http://thesiteiloginto.org/someotherpage");
}
}
// Store Cookies
CookieCollection Cookies;
void GetCookies(string cookieUrl)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(cookieUrl);
request.CookieContainer = new CookieContainer();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
// Store Cookies
Cookies = response.Cookies;
}
}
bool IsLoggedIn()
{
GetCookies(_cookieUrl);
CookieCollection cookies = Cookies;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(loginUrl);
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
request.CookieContainer = new CookieContainer();
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
string postData = "login=" + username +
"&password=" + password +
"&_xfToken=" + xfToken +
"&cookie_check=" + cookie_check +
"&redirect=" + redirect;
byte[] bytes = Encoding.UTF8.GetBytes(postData);
request.ContentLength = bytes.Length;
if (cookies != null)
{
Console.WriteLine("Cookies are present");
Console.WriteLine(Cookies.Count);
Console.WriteLine(Cookies[0].Value);
request.CookieContainer.Add(cookies);
}
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
WebResponse response = request.GetResponse();
using (Stream stream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(stream))
{
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(reader.ReadToEnd());
bool _loggedIn = false;
try
{
var uniqueNodeTest = doc.DocumentNode.SelectSingleNode("//*[@id=\"navigation\"]/div/nav/div/ul[2]/li[1]/a/strong[1]");
if (uniqueNodeTest.InnerText.Trim().ToLower() == uniqueNodeName)
{
Console.WriteLine("Logged in");
_loggedIn = true;
}
}
catch (Exception ex)
{
Console.WriteLine("Ops! [Login] @ SelectSingleNode\n" + ex.Message);
_loggedIn = false;
}
return _loggedIn;
}
}
}
}
void GetPage(string url)
{
if (Cookies != null)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.PreAuthenticate = true;
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(Cookies);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
var pageSource = reader.ReadToEnd();
// Retuns false, meaning i am not logged in
//Where do i go from here?
Console.WriteLine(pageSource.Contains("Log Out"));
}
}
}
}
Console:
Cookies are present 1 22a6c5a4c5557a7f7db36f50a1d746f1 Logged in False
Come puoi vedere, ho effettuato l'accesso dopo il primo test, ma non riesco a rimanere connesso quando cerco di esplorare ulteriormente il riutilizzo dei cookie.
Cosa non sto prendendo in considerazione? Come posso rimanere connesso al sito?
Usa CookieContainer
come classe per memorizzarli localmente.
Quando recuperi la risposta, metti tutti i cookie nel CookieContainer. Quando si prepara la richiesta, basta impostare la richiesta.CookieContainer sul proprio oggetto nella nuova chiamata.
Questo è il codice che ho usato per salvare i miei cookies in un mio progetto. Dato che fa parte di una classe HttpSession completamente sviluppata per il tipo di richieste che stai facendo, noterai che sia la risposta che il contenitore dei cookie sono variabili di classe.
/// <summary>
/// Fetches the new cookies and saves them in the cookie jar.
/// </summary>
private void SaveNewCookies()
{
try
{
foreach (Cookie c in this.m_HttpWebResponse.Cookies)
{
if (c.Domain.Length > 0 && c.Domain[0] == '.')
c.Domain = c.Domain.Remove(0, 1);
this.m_CookieJar.Add(new Uri(this.m_HttpWebResponse.ResponseUri.Scheme + "://" + c.Domain), c);
}
if (this.m_HttpWebResponse.Cookies.Count > 0)
this.BugFixCookieDomain(this.m_CookieJar);
}
catch
{
// no new cookies
}
}
Come vedi, questo contiene anche alcune correzioni di bug più piccole. La funzione BugFixCookieDomain citata è una correzione specifica per il framework 3.5, che puoi trovare qui , ma se hai passato oltre a 4.0 e oltre non ti sarà particolarmente utile.