HttpClient, Forms Authentication
От: Qbit86 Кипр
Дата: 19.05.13 12:03
Оценка:
Добрый день, уважаемые коллеги!

Помогите, пожалуйста, разобраться с программной авторизацией на некотором сайте (для примера ниже взят 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.
Глаза у меня добрые, но рубашка — смирительная!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.