Как я могу получить куки HttpOnly в Windows Phone 8?

Я работаю в проекте Windows Phone 8 PCL. Я использую сторонний REST API, и мне нужно использовать несколько файлов cookie HttpOnly, созданных API. Кажется, что получить / получить доступ к файлам cookie HttpOnly из CookieContainer HttpClientHandler невозможно, если вы не используете отражение или какой-либо другой бэкдор.

Мне нужно получить эти куки и отправлять их в последующих запросах, иначе я не смогу работать с этим API - как я могу это сделать? Вот как выглядит мой текущий код запроса:

Заранее спасибо.

//Some request
HttpRequestMessage request = new HttpRequestMessage();
HttpClientHandler handler = new HttpClientHandler();

//Cycle through the cookie store and add existing cookies for the susbsequent request
foreach (KeyValuePair<string, Cookie> cookie in CookieManager.Instance.Cookies)
{
            handler.CookieContainer.Add(request.RequestUri, new Cookie(cookie.Value.Name, cookie.Value.Value));
}

//Send the request asynchronously
HttpResponseMessage response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();

//Parse all returned cookies and place in cookie store
foreach (Cookie clientcookie in handler.CookieContainer.GetCookies(request.RequestUri))
{
     if (!CookieManager.Instance.Cookies.ContainsKey(clientcookie.Name))
                CookieManager.Instance.Cookies.Add(clientcookie.Name, clientcookie);
            else
                CookieManager.Instance.Cookies[clientcookie.Name] = clientcookie;
}

HttpClient httpClient = new HttpClient(handler);

2 ответа

Файл cookie HttpOnly находится внутри CookieContainer, только он не открыт. Если вы установите тот же экземпляр этого CookieContainer для следующего запроса, он установит там скрытый cookie (если запрос сделан на тот же сайт, который указан cookie).

Это решение будет работать до тех пор, пока вам не потребуется сериализация и десериализация CookieContainer, поскольку вы восстанавливаете состояние. Как только вы это сделаете, вы потеряете куки HttpOnly, скрытые внутри CookieContainer. Таким образом, более постоянным решением было бы использование Sockets непосредственно для этого запроса, чтение необработанного запроса в виде строки, извлечение файла cookie и установка его для следующих запросов. Вот код для использования сокетов в Windows Phone 8:

public async Task<string> Send(Uri requestUri, string request)
{
   var socket = new StreamSocket();
   var hostname = new HostName(requestUri.Host);
   await socket.ConnectAsync(hostname, requestUri.Port.ToString());

   var writer = new DataWriter(socket.OutputStream);
   writer.WriteString(request);
   await writer.StoreAsync();

   var reader = new DataReader(socket.InputStream) 
   { 
      InputStreamOptions = InputStreamOptions.Partial 
   };
   var count = await reader.LoadAsync(512);

    if (count > 0)
      return reader.ReadString(count);
    return null;
}

Существует также вторая возможность - вручную просматривать заголовки ответов, захватывать, а затем анализировать заголовки Set-Cookie, используя несколько пользовательских кодов.

Это выглядит примерно так, когда вы собираетесь сопоставить и сохранить один PHPSESSID печенье (предположим LatestResponse твой HttpResponseMessage содержащий ответ сайта):

if (LatestResponse.Headers.ToString().IndexOf("Set-Cookie:") != -1) try
        {
            string sid = LatestResponse.Headers.ToString();
            sid = sid.Substring(sid.IndexOf("Set-Cookie:"), 128);
                if (sid.IndexOf("PHPSESSID=") != -1)
                {
                    settings.Values["SessionID"] = SessionID = sid.Substring(sid.IndexOf("PHPSESSID=") + 10, sid.IndexOf(';') - sid.IndexOf("PHPSESSID=") - 10);
                    handler.CookieContainer.Add(new Uri("http://example.com", UriKind.Absolute), new System.Net.Cookie("PHPSESSID", SessionID));
                }
        } catch (Exception e) { 
            // your exception handling
        }

Обратите внимание, что этот код вставляет куки в CookieContainer для жизни этого объекта, если вручную не удалены. Если вы хотите включить его в новый объект, просто выберите правильное значение настройки и добавьте его в новый контейнер.

Другие вопросы по тегам