Получение файлов 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");