Получение файлов cookie в веб-браузере - WP7

Чтобы войти в определенную часть веб-сайта, пользователям моего приложения требуется свой cookie. Для этого мне нужно взять его и передать URL.

Кто-нибудь знает, как получить cookie-файлы определенного веб-сайта из браузера?

Я видел этот метод, но не совсем ясно.

Спасибо, ТП.

5 ответов

Начиная с версии WP 7.1 Mango, если это возможно, см. Обзор управления веб-браузером для Windows Phone. Недавно он был немного обновлен, и оказалось, что они действительно добавили некоторую поддержку для поиска файлов cookie из WebBrowser. Внизу страницы вы найдете крошечную ссылку GetCookies(WebBrowser), указывающую на описание нового класса: WebBrowserExtensions с помощью этого очень удобного метода. Да, у этого класса есть только один единственный член. Это метод расширения, я полагаю, что никаких объяснений по этому поводу не требуется.

Я не слишком много играл с этим методом, но, похоже, это позволит вам получить доступ к тому же самому трюку с JS: набору cookie для текущего URL. Это, вероятно, не позволит ничего устанавливать или просматривать файлы cookie для других URL-адресов. Может быть, если вы будете усердно играть с CookieContainer, то получите, но я сомневаюсь.

В версии 7.0 я изо всех сил пытался добиться прозрачности файлов cookie для моего приложения. Короче говоря, мое приложение выполняло несколько фоновых HTTP-запросов, а также имело веб-браузер для отображения некоторого онлайн-контента - и "было бы здорово", если бы оба источника соединений отправляли на сервер одни и те же файлы cookie., мое приложение должно было сделать первый запрос, а затем позволить браузеру перемещаться. При таких требованиях практически не было способа добиться согласованности файлов cookie - ба, даже с нынешним новым и великолепным методом GetCookie, я полагаю, это будет чертовски сложно. Итак, по сути - это было возможно, но нужно было использовать какой-то скрытый API, который публично присутствует на телефоне, но скрыт в SDK. API доступен (общедоступный) класс System.Net.Browser.WebRequestCreator, свободно доступный. Особенность в том, что в SDK этот класс имеет единственное общедоступное статическое свойство "IWebRequestCreate ClientHttp" с методом "Create", который можно использовать для "фабрикации" ваших "необработанных" http-соединений - в случае, если вы не хотите использовать WebClient для некоторая причина. На телефоне и в эмуляторе есть второе общедоступное статическое свойство под названием "IWebRequestCreate BrowserHttp", которое легко возвращается Reflection:

PropertyInfo brwhttp = typeof(System.Net.Browser.WebRequestCreator)
    .GetProperty("BrowserHttp")

с этим свойством вы сможете получить "специальный" внутренний экземпляр IWebRequestCreate, который используется внутри WebBrowser. Открыв свои фоновые HTTP-запросы с этим классом, вы получите ваши куки автоматически настроенными так, как если бы они были созданы / отправлены элементом управления WebBrowser, но, в свою очередь - вы НЕ сможете изменять заголовки http, предоставлять пользователю аутентификацию http и ни несколько вещей низкого уровня - потому что все эти настройки будут синхронизированы с данными WebBrowser, хранящимися для текущего "экземпляра пользователя системы", если мне будет позволено вызывать его как таковой на однопользовательском устройстве Phone хе. Взаимодействие между соединениями и WebBrowser работает в обоих направлениях - если ваше HTTP-соединение (созданное с использованием "скрытого свойства") получает какие-либо настройки / куки / и т. Д. - тогда WebBrowser мгновенно заметит их и обновит свой собственный кэш. Нет потери cookie / сессии ни на одной из сторон!

Если вам нужно пассивно получать куки для ваших последующих подключений после первой навигации в WebBrowser - пожалуйста, используйте метод GetCookie или JS. Но если вам нужно, чтобы ваш код был первым, а затем передал authz в WebBrowser - вам, вероятно, придется копать глубже и использовать вышеописанное. Он скрыт, поэтому, пожалуйста, сначала прибегните к другим средствам!

... и не спрашивайте меня, как я нашел это или сколько времени это заняло:P приятно провести время с этим

//edit: я только что узнал, что свойство BrowserHttp - это обычный способ Silverlight для доступа к фабрике соединений браузера, см. BrowserHttp. Кажется, что он был спрятан только в "miniSilverlight", написанном для платформы WP7!

// Ensure this is set to true BEFORE navigating to the page
webBrowser1.IsScriptEnabled = true;

// Once the page has loaded, you can read the cookie string
string cookieString = webBrowser1.InvokeScript("eval", new string[] { "document.cookie;" }) as string;

Переменная cookieString будет содержать полный файл cookie для документа. Затем вы можете разобрать строку.

Для этого есть класс расширения WebBrowser:

CookieCollection tempCookies = Microsoft.Phone.Controls.WebBrowserExtensions.GetCookies(this.BrowserControl);

Как уже предлагал @quetzalcoatl, вы можете использовать внутренний экземпляр WebRequestCreator для обмена файлами cookie между экземплярами браузера и экземплярами WebRequest. Вы не можете получить прямой доступ к файлам cookie, я думаю, что это всего лишь мера безопасности со стороны Microsoft.

Этот код ниже создает объект WebReqeust, связанный с CookieContainer экземпляра WebBrowser. Затем он отправляет URL-адрес, чтобы войти в систему пользователя и сохранить куки в контейнере. После этого все экземпляры браузера в экземпляре приложения будут иметь требуемый набор файлов cookie.

var browser = new WebBrowser();
var brwhttp = typeof (WebRequestCreator).GetProperty("BrowserHttp");
var requestFactory = brwhttp.GetValue(browser, null) as IWebRequestCreate;
var uri = new Uri("https://www.login.com/login-handler");

var req = requestFactory.Create(uri);
req.Method = "POST";

var postParams = new Dictionary<string, string> { 
    {"username", "turtlepower"}, 
    {"password": "ZoMgPaSSw0Rd1"}
};

req.BeginGetRequestStream(aReq => {

    var webRequest = (HttpWebRequest)aReq.AsyncState;
    using (var postStream = webRequest.EndGetRequestStream(aReq)) {

        // Build your POST request here
        var postDataBuilder = new StringBuilder();
        foreach (var pair in paramsDict) {
            if (postDataBuilder.Length != 0) {
                postDataBuilder.Append("&");
            }
            postDataBuilder.AppendFormat("{0}={1}", pair.Key, HttpUtility.UrlEncode(pair.Value));
        }

        var bytes = Encoding.UTF8.GetBytes(postDataBuilder.ToString());
        postStream.Write(bytes, 0, bytes.Length);
    }

    // Receive response 
    webRequest.BeginGetResponse(aResp => {

        var webRequest2 = (HttpWebRequest) aResp.AsyncState;

        webRequest = (HttpWebRequest)aResp.AsyncState;
        string resp;

        using (var response = (HttpWebResponse)webRequest2.EndGetResponse(aResp)) {
            using (var streamResponse = response.GetResponseStream()) {
                using (var streamReader = new System.IO.StreamReader(streamResponse)) {
                    resp = streamReader.ReadToEnd();
                }
            }
        }

    }, webRequest);
}, req);

Одной из проблем, которую я не смог решить, были исключения, возникающие, когда сервер возвращает 302 - похоже, выдается ошибка WebException с описанием "Not found".

Подход, описанный в посте, который вы связали, заключается в использовании WebBrowser Контрольного InvokeScript метод для запуска некоторого JavaScript. Тем не менее, пост, похоже, использует коллекцию "куки", которой на самом деле не существует.

 string cookie = myWebBrowser.InvokeScript("document.cookie") as string;

Теперь для сложной части полученная вами строка содержит все соответствующие пары имя / значение cookie для страницы, значения которой по-прежнему кодируются в формате Url. Вам нужно будет проанализировать возвращенную строку на предмет нужного вам значения.

Смотрите документацию по document.cookie.

Редактировать:

Глядя на это свежо, вместо того, чтобы полагаться на почту, InvokeScript вызывает именованную функцию в окне браузера хоста. Следовательно, страница, отображаемая в WebBrowser, сама должна включать такую ​​функцию:

 function getCookie() { return document.cookie; }

Тогда InvokeScript будет выглядеть так:

 string cookie = myWebBrowser.InvokeScript("getCookie");
Другие вопросы по тегам