Добрый день, уважаемые коллеги!
Помогите, пожалуйста, разобраться с программной авторизацией на некотором сайте (для примера ниже взят RSDN).
К сожалению в веб-программировании и сетевом взаимодействии разбираюсь слабо, так что возможны фундаментальные бреши в понимании процесса.
Для запуска нижеприведённого кода в LINQPad (C# Statements) нужно подключить (F4) пространства имён System.Net и System.Net.Http из одноимённых сборок.
Используются классы HttpClient, HttpRequestMessage и HttpResponseMessage из .NET 4.5. Документации и примеров по ним негусто.
Не используются классы WebClient, HttpWebRequest и HttpWebResponse из .NET 1.1.
Ожидаемое поведение кода (при правильно введённых логине и пароле): делается POST-запрос к серверу, передавая заполненные input'ы странички аутентификации; сервер возвращает куки, в которых хранится идентификатор сессии; делается GET-запрос какой-нибудь приватной странички, она сохраняется локально.
Фактическое поведение кода: сервер возвращает куки, похожие на идентификатор сессии; но последущее обращение к приватной страничке не авторизует, и возвращает вместо неё страничку логина.
В чём проблема?
var cookieContainer = new CookieContainer();
var authHandler = new HttpClientHandler
{
UseProxy = false, Proxy = null,
UseCookies = true, CookieContainer = cookieContainer,
AllowAutoRedirect = false,
};
var authClient = new HttpClient(authHandler, disposeHandler: true);
HttpContent authRequestContent = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "lognm", "JaneDoe" },
{ "password", "p@$$w0rd" },
});
var authRequestUri = new Uri(@"http://rsdn.ru/Users/Login.aspx");
using (var authRequest = new HttpRequestMessage(HttpMethod.Post, authRequestUri) { Content = authRequestContent })
using (var authResponse = await authClient.SendAsync(authRequest))
{
if (authResponse.StatusCode == HttpStatusCode.OK)
{
// Среди заголовков есть «Set-Cookie».
authResponse.Headers.Dump("Auth response headers");
// В коллекции куки появляются новые значения.
cookieContainer.GetCookies(new Uri(@"http://rsdn.ru")).Dump("Cookies");
}
}
var getHandler = new HttpClientHandler
{
UseProxy = false, Proxy = null,
UseCookies = true, CookieContainer = cookieContainer,
AllowAutoRedirect = true,
};
var getClient = new HttpClient(getHandler, disposeHandler: true);
var getRequestUri = new Uri(@"http://rsdn.ru/Users/Private/Favorites.aspx");
using (var getRequest = new HttpRequestMessage(HttpMethod.Get, getRequestUri))
using (var getResponse = await getClient.SendAsync(getRequest))
{
if (getResponse.StatusCode == HttpStatusCode.OK)
{
var dirPath = Path.GetTempPath();
var fileName = DateTime.Now.TimeOfDay.ToString().Replace(':', '-') + ".html";
var filePath = Path.Combine(dirPath, fileName);
using (Stream fs = File.Create(filePath))
{
await getResponse.Content.CopyToAsync(fs);
}
filePath.Dump("File saved");
}
}
// To be disposed: authClient, getClient.