Ответ PCL HttpClient игнорирует файлы cookie без домена

Я работаю над приложением на основе REST, которое подключается к Office365. Приложение будет доступно на нескольких платформах, поэтому я создал переносимую библиотеку классов для обработки всей логики, включая аутентификацию. PCL предназначен для Windows Phone 7.1 и более поздних версий и включает клиентские библиотеки Microsoft HTTP (NuGet), необходимые для приложений Windows Phone 7.1.

Последним шагом аутентификации для Office365 является получение файла cookie FedAuth с сайта, и именно здесь у меня возникла проблема.

Код, который я использую для получения файла cookie:

var handler = new HttpClientHandler();
handler.AllowAutoRedirect = false;
var newClient = new HttpClient(handler);
var newResponse = await newClient.PostAsync(host + "/_forms/default.aspx?wa=wsignin1.0", new StringContent(binarySecurityToken));

Переменная «host» — это просто URL-адрес сайта Office365 и бинарныйSecurityToken, который я получил из предыдущих запросов. Эти вещи одинаково хорошо работают во всех приложениях: запускаю ли я код PCL из контекста приложения Windows Phone 7.1, приложения Windows Phone 8, приложения Windows 8 или даже консольного приложения, я получаю точно такой же ответ (см. ниже), который содержит файл cookie FedAuth. Это я проверил с помощью Fiddler.

Затем я пытаюсь получить файл cookie для повторного использования в последующих запросах.

var cookieCollection = handler.CookieContainer.GetCookies(new Uri(host));
foreach (var cookie in cookieCollection)
{
    if (cookie.Name.StartsWith("FedAuth"))
    {
        //TODO: Store the cookie.
        return true;
    }
}

Это приводит к следующему результату: В Windows Phone 7.1 переменная cookieCollection содержит только файл cookie rtFa. На других платформах он содержит все три файла cookie «RpsContextCookie», «rtFa», «FedAuth».

Windows Phone 7.1 отличается от других приложений тем, что это единственная платформа, которая фактически использует HttpClient из пакета NuGet. На других платформах есть собственный HttpClient, который заменяется магией PCL.

Вероятно, проблема вызвана тем, что файл cookie FedAuth не имеет домена. Я пробовал использовать .GetCookies(null) и различные варианты .GetCookies(new Uri("something", UriKind.Relative)), все они приводят к исключению. Я также безуспешно пытался изменить большинство свойств HttpClientHandler.

Кто-нибудь сталкивался с этой проблемой и, возможно, решил ее? Или просто предложение о том, что я мог бы попробовать?

Ответ, который я получаю на .PostAsync выше, одинаков на всех платформах, и, согласно Fiddler, необработанный ответ:

HTTP/1.1 302 Found
Cache-Control: no-cache, no-store
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Expires: -1
Location: /
Server: Microsoft-IIS/7.5
X-SharePointHealthScore: 0
X-AspNet-Version: 4.0.30319
Set-Cookie: RpsContextCookie=; path=/
Set-Cookie: rtFa=+13jGMMp0A0V+driESaO30ixYclFCRjEvS2jMSwXPfQcrefiJvLEExxYu7V+1JZHM6X5JWeuL70jb3/N/Q/hUTwoAiC/XLJZ1QfERi4aUt8AAVF4ekcNyMdWnj65foDwPkhaV5z8whNSZQigBFD/2Vc1xMTH0ukHbS4cbtJO5U28/4g66vgIZg7dGpNOZg2jDt+HF3GSQ4/W+T1oS9/F5e+Pbwd0p8mqPhkGjL+M7IptmkeHoIqVcS4Ps25dM6q1AniLiv/3NujYmrQjseaEYZ2aaCfc7ZHX7LygBZm8KsoGNyTYRPmC+hZ7tsDq6wfto+xVpX1scggsU0+Qty3DPWUiwy1bBy8JR0znFG0+eDt9uBOQzqfOSjVvd8WNIKUFIAAAAA==; domain=sharepoint.com; path=/; HttpOnly
Set-Cookie: FedAuth=77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48U1A+RmFsc2UsMGguZnxtZW1iZXJzaGlwfDEwMDMwMDAwODc5MTUwMGVAbGl2ZS5jb20sMCMuZnxtZW1iZXJzaGlwfHRtakB3aWxkY293Lm9ubWljcm9zb2Z0LmNvbSwxMzAzNDIwOTYxNDAxMTIxMzMsRmFsc2UsV2lSQjlUVTdOSTk0MUpKRWZ5d1JDNTFPYUphMVpWNkJqWWdaVGM3MU00U3lqL2VkTnF6dVJpbXdEMnpEWk9oR1lybkFsNnpWb3M4V0FBZDk1VVYrZkt5dlkwQ3dqRTlyaEhEc256bkZUeENoODU1Rm1JZmxoYVBkMTFQS2VjWnFJN0N4OUxUOHk4enZDaVNUTGNQMzR2K3NOeHk1YXBMZ2NIWDNHR3JMcG1Ic24rQzAzUkUzakNDQWhma2F3RVRQbk03R3JycVk5amJseHJmNVNhNHZxMk91NlN1cGszZnpQMUZQTzJBc1UrRXZvSDgvWTllR2Y3c2x2dStvMnVlN3hZLy9VQ1lYU1U4b3AzckZ6c2laK0wwN1NrUnZYMTZjVklUVVZJZ0x6TGIxaTJLd2lwNGp6RHgwRFdmVWF0Rk42UVFaNWhHRzMyOHRJZjI2RXo4YldnPT0saHR0cHM6Ly93aWxkY293LnNoYXJlcG9pbnQuY29tLzwvU1A+; path=/; secure; HttpOnly
SPRequestGuid: 5bb2689c-d7c5-c07c-4890-ee32437f15f5
request-id: 5bb2689c-d7c5-c07c-4890-ee32437f15f5
SPRequestDuration: 125
SPIisLatency: 2
X-Powered-By: ASP.NET
MicrosoftSharePointTeamServices: 16.0.0.2308
X-Content-Type-Options: nosniff
X-MS-InvokeApp: 1; RequireReadOnly
P3P: CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI"
Date: Thu, 09 Jan 2014 21:46:53 GMT
Content-Length: 118

<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href="/">here</a>.</h2>
</body></html>

person Thomas Jørgensen    schedule 11.01.2014    source источник


Ответы (1)


Я нашел ответ здесь: -windows-phone-8pcl?forum=wpdevelop" rel="nofollow">Доступ к файлам cookie HTTPOnly из Windows Phone 8/PCL.

Прочитав сообщение, я понял, что допустил ошибку выше: я получал не файл cookie «rtFa» в приложении Windows Phone 7.1, а «RpsContextCookie». Оба файла cookie, к которым я не мог получить доступ, были помечены как HttpOnly.

Я также понял, что мне не нужен прямой доступ к файлам cookie. Вместо этого я мог бы просто повторно использовать handler.CookieContainer. Итак, мой код теперь выглядит так:

var handler = new HttpClientHandler();
handler.AllowAutoRedirect = false;
var newClient = new HttpClient(handler);
var newResponse = await newClient.PostAsync(host + "/_forms/default.aspx?wa=wsignin1.0", new StringContent(binarySecurityToken));
this._cookieContainer = handler.CookieContainer;
return true;

this._cookieContainer — это просто поле класса для хранения контейнера cookie. Затем, когда я прохожу аутентификацию и выполняю запросы, которые являются фактической целью приложения, я делаю следующее:

var handler = new HttpClientHandler(){ CookieContainer = this._cookieContainer };
var client = new HttpClient(handler);
var response = await client.GetAsync(host + "something");

Итак, суть такова: я не могу получить доступ к файлам cookie HttpOnly, но мне это не нужно. Я просто повторно использую контейнер cookie, и файлы cookie автоматически включаются в следующий запрос.

Это работает как в приложениях Windows Phone 7.1, так и в приложениях Windows Phone 8, консольных приложениях и т. д.

person Thomas Jørgensen    schedule 11.01.2014
comment
Если вы повторно используете один и тот же экземпляр HttpClient на протяжении всего жизненного цикла вашего приложения, вам даже не нужно беспокоиться о повторном назначении файла cookie. - person Darrel Miller; 11.01.2014
comment
Мне нужно хотя бы повторно использовать контейнер cookie. Все на более высоком уровне, которое также включает это, например, экземпляр HttpClient или некоторый класс-оболочка, содержащий экземпляр HttpClient, также является допустимым выбором. - person Thomas Jørgensen; 13.01.2014