Intereting Posts
Гибкий дизайн интерфейса ведения журнала в C # Создание папки в библиотеке документов с помощью приемника событий Sharepoint Как получить, какой переключатель установлен из группового ящика? MVC 5 BeginCollectionItem с частичным CRUD Тупик при блокировке вызова async HttpClient в продолжении задачи ASP.Net Web Api – ApiExplorer не содержит никаких ApiDescriptions C # XML-данные в словарь C #: неявный оператор и методы расширения как перенаправить на страницу входа, если пользователь напрямую вводит URL-адрес в браузере с помощью ASP.NET COM-объект, который был отделен от его базового RCW, не может быть использован – почему это происходит? ИЛИ, И Оператор закрытие SQLDataReaders – как узнать, закрыты ли они? Отображение диаграмм HTML5 в частичных представлениях показывает только пустые данные Как получить позиции мыши в моей модели просмотра Преобразуйте всю первую букву в верхний регистр, оставьте ниже для каждого слова

CookieContainer обработки путей (Кто съел мой cookie?)

Я работаю над проектом, который включает в себя некоторые основные веб-сканирования. Я успешно использовал HttpWebRequest и HttpWebResponse. Для обработки файлов cookie у меня есть только один CookieContainer, который я назначаю HttpWebRequest.CookieContainer каждый раз. Я автоматически заполняю новые cookies каждый раз и не требует дополнительной обработки от меня. Все это прекрасно работает, пока некоторое время назад один из веб-сайтов, которые раньше работали, внезапно прекратил работать. Я уверен, что это проблема с файлами cookie, но я не записывал cookies, когда он работал, поэтому я не уверен на 100%.

Мне удалось имитировать проблему, поскольку я вижу ее со следующим кодом:

CookieContainer cookieJar = new CookieContainer(); Uri uri1 = new Uri("http://www.somedomain.com/some/path/page1.html"); CookieCollection cookies1 = new CookieCollection(); cookies1.Add(new Cookie("NoPathCookie", "Page1Value")); cookies1.Add(new Cookie("CookieWithPath", "Page1Value", "/some/path/")); Uri uri2 = new Uri("http://www.somedomain.com/some/path/page2.html"); CookieCollection cookies2 = new CookieCollection(); cookies2.Add(new Cookie("NoPathCookie", "Page2Value")); cookies2.Add(new Cookie("CookieWithPath", "Page2Value", "/some/path/")); Uri uri3 = new Uri("http://www.somedomain.com/some/path/page3.html"); // Add the cookies from page1.html cookieJar.Add(uri1, cookies1); // Add the cookies from page2.html cookieJar.Add(uri2, cookies2); // We should now have 3 cookies Console.WriteLine(string.Format("CookieJar contains {0} cookies", cookieJar.Count)); Console.WriteLine(string.Format("Cookies to send to page1.html: {0}", cookieJar.GetCookieHeader(uri1))); Console.WriteLine(string.Format("Cookies to send to page2.html: {0}", cookieJar.GetCookieHeader(uri2))); Console.WriteLine(string.Format("Cookies to send to page3.html: {0}", cookieJar.GetCookieHeader(uri3))); 

Это имитирует посещение двух страниц, оба из которых устанавливают два куки. Затем он проверяет, какое из этих файлов cookie будет установлено на каждую из трех страниц.

Из двух файлов cookie один устанавливается без указания пути, а другой имеет указанный путь. Когда путь не указан, я предположил, что файл cookie будет отправлен на любую страницу в этом домене, но, похоже, он будет отправлен обратно на эту конкретную страницу. Теперь я предполагаю, что это правильно, поскольку оно последовательное.

Основная проблема для меня – это обработка файлов cookie с указанным путем. Конечно, если указан путь, cookie должен быть отправлен на любую страницу, содержащуюся в этом пути. Итак, в приведенном выше коде «CookieWithPath» должен быть действительным для любой страницы внутри / some / path /, которая включает page1.html, page2.html и page3.html. Конечно, если вы прокомментируете два экземпляра «NoPathCookie», то «CookieWithPath» будет отправлен на все три страницы, как и следовало ожидать. Однако с включением «NoPathCookie», как указано выше, «CookieWithPath» отправляется только на страницы2.html и page3.html, но не на page1.html.

Почему это, и это правильно?

В поисках этой проблемы я столкнулся с обсуждением проблемы с обработкой домена в CookieContainer, но не смог найти никакого обсуждения путей обработки.

Я использую Visual Studio 2005 / .NET 2.0

Когда путь не указан, я предположил, что файл cookie будет отправлен на любую страницу в этом домене, но, похоже, он будет отправлен обратно на эту конкретную страницу. Теперь я предполагаю, что это правильно, поскольку оно последовательное.

Да, это правильно. Всякий раз, когда домен или путь не указаны, он берется из текущего URI.

Хорошо, давайте посмотрим на CookieContainer. Этот метод является InternalGetCookies (Uri) . Вот интересная часть:

 while (enumerator2.MoveNext()) { DictionaryEntry dictionaryEntry = (DictionaryEntry)enumerator2.get_Current(); string text2 = (string)dictionaryEntry.get_Key(); if (!uri.AbsolutePath.StartsWith(CookieParser.CheckQuoted(text2))) { if (flag2) { break; } else { continue; } } flag2 = true; CookieCollection cookieCollection2 = (CookieCollection)dictionaryEntry.get_Value(); cookieCollection2.TimeStamp(CookieCollection.Stamp.Set); this.MergeUpdateCollections(cookieCollection, cookieCollection2, port, flag, i < 0); if (!(text2 == "/")) { continue; } flag3 = true; continue; } 

enumerator2 здесь (отсортированный) список путей cookie. Он сортируется таким образом, что более конкретные пути (например, /directory/subdirectory/ ) идут до менее конкретных (например, /directory/ ), а в противном случае - в лексикографическом порядке ( /directory/page1 идет перед /directory/page2 ) ,

Код действительно имеет следующее: он выполняет итерацию по этому списку путей cookie до тех пор, пока не найдет первый путь, который является префиксом для запрошенного пути URI. Затем он добавляет cookies по этому пути к выходу и устанавливает flag2 в значение true , что означает «ОК, я, наконец, нашел место в списке, которое действительно связано с запрошенным URI». После этого первый встречный путь, который НЕ является префиксом для запрошенного пути URI, считается концом связанных путей, поэтому код перестает искать cookies, делая break .

Очевидно, что это какая-то оптимизация для предотвращения сканирования всего списка и, по-видимому, работает, если ни один из путей не ведет к конкретной странице. Теперь, для вашего случая, список путей выглядит следующим образом:

 /some/path/page1.html /some/path/page2.html /some/path/ 

Вы можете проверить это с помощью отладчика, глядя вверх ((System.Net.PathList)(cookieJar.m_domainTable["www.somedomain.com"])).m_list в окне просмотра

Итак, для URI 'page1.html' код разбивается на элемент page2.html, не имея возможности обработать также /some/path/ item.

В заключение: это, очевидно, еще одна ошибка в CookieContainer. Я считаю, что это нужно сообщать о подключении.

PS: Это слишком много ошибок для одного classа. Я только надеюсь, что парень из MS, который написал тесты для этого classа, уже уволен.