Общие сведения о файлах Cookie ASP.NET

Обновлен: Ноябрь 2007

Файл Cookie — это небольшой фрагмент текста, сопровождающий запросы и страницы при их переходах между веб-сервером и обозревателем. Файл Сookie содержит сведения, которые веб-приложение может считать всякий раз при посещении веб-узла пользователем.

В этом разделе рассматриваются следующие темы:

  • Сценарии

  • Базовые сведения

  • Примеры кода

  • Ссылки на классы

  • Дополнительные источники

  • Новые возможности

Сценарии

Файлы Сookie позволяют веб-приложениям хранить сведения о пользователе. Например, при посещении пользователем узла можно использовать файлы Сookie для хранения настроек пользователя или другой информации. При следующем посещении пользователем веб-узла приложение может извлечь сохраненную ранее информацию.

К началу

Базовые сведения

Файл Cookie — это небольшой фрагмент текста, сопровождающий запросы и страницы при их переходах между веб-сервером и обозревателем. Файл Сookie содержит сведения, которые веб-приложение может считать всякий раз при посещении веб-узла пользователем.

Например, если пользователь запрашивает страницу с веб-узла и приложение отправляет не только страницу, но и файл Сookie, содержащий дату и время получения страницы обозревателем пользователя, то обозреватель получит файл Сookie и сохранит его в папке на жестком диске пользователя.

В дальнейшем при повторных запросах страницы с веб-узла пользователем, когда пользователь вводит URL-адрес, обозреватель выполняет поиск файла Сookie, связанного с этим URL-адресом, на локальном жестком диске. Если файл Сookie существует, то обозреватель отправляет его на веб-узел вместе с запросом страницы. Затем приложение может определить дату и время последнего посещения веб-узла пользователем. Можно использовать эти сведения для отображения сообщения пользователю или для проверки даты окончания срока действия.

Файлы Сookie связаны с веб-узлом, а не с определенной страницей, поэтому обозреватель и сервер будут обмениваться сведениями файлов Сookie независимо от того, какую страницу запрашивает пользователь с веб-узла. При посещении пользователем разных веб-узлов каждый веб-узел может отправить файл Сookie обозревателю пользователя; обозреватель хранит все файлы Сookie отдельно.

Файлы Сookie помогают веб-узлам хранить сведения о посетителях. Файлы Сookie — это один из способов поддержания непрерывности в веб-приложении — то есть, выполнения управления состоянием. За исключением короткого промежутка времени, в течение которого выполняется обмен информацией, обозреватель отключен от веб-сервера. Каждый запрос пользователя на веб-сервер обрабатывается независимо от любого другого запроса. Однако в большинстве случаев полезно, чтобы веб-сервер распознавал пользователей при запросе страницы. Например, веб-сервер веб-узла интернет-магазина отслеживает отдельных покупателей, что позволяет веб-узлу управлять корзинами для покупок и другой информацией, связанной с конкретными пользователями. Следовательно, файл Сookie представляет собой своего рода визитную карточку, идентификатор, содержащий нужные сведения, помогающие приложению понять, что нужно выполнять дальше.

Файлы Сookie используются для многих целей, которые связаны с помощью веб-узлу в запоминании пользователей. Например, проводящий опрос веб-узел может использовать файл Сookie просто как логическое значение для указания, участвовал ли обозреватель пользователя в голосовании, чтобы пользователь не мог проголосовать дважды. Веб-узел, требующий от пользователя входа в систему, может использовать файл Сookie для записи того, что пользователь уже вошел в систему, чтобы избежать необходимости продолжения ввода пользователем учетных данных.

Ограничения файлов Сookie

Большинство обозревателей поддерживают файлы Сookie размером до 4096 байт. Из-за такого низкого верхнего предела файлы Сookie лучше использовать для хранения малых объемов данных или, лучше всего, идентификатора, например, идентификатора пользователя. Затем идентификатор пользователя может использоваться для идентификации пользователя и считывания сведений о пользователе из базы данных или из другого хранилища данных. (сведения о влиянии хранения сведений о пользователе на безопасность см. в приведенном ниже подразделе "Файлы Сookie и безопасность").

Также обозреватели накладывают ограничения на количество файлов Cookie, которое веб-узел может сохранить на компьютере пользователя. Большинство обозревателей разрешают хранение только 20 файлов Cookie на один веб-узел, при попытке сохранения большего количества самые старые файлы Cookie удаляются. Также в некоторых обозревателях устанавливается абсолютный лимит, обычно равный 300, на количество файлов Cookie, которое они готовы принять всего, от всех веб-узлов.

Ограничение файлов Cookie, с которым можно встретиться, заключается в том, что пользователи могут настроить обозреватель на отказ от файлов Cookie. Если определить политику конфиденциальности P3P и расположить ее в корне веб-узла, то больше обозревателей будут принимать файлы Cookie с веб-узла. Однако возможна ситуация которая вынудит вообще не использовать файлы Cookie и использовать другой механизм хранения информации, связанной с конкретным пользователем. Распространенным методом хранения сведений о пользователе является состояние сеанса, но оно зависит от файлов Cookie, как объясняется далее в подразделе "Файлы Cookie и состояние сеанса".

ms178194.alert_note(ru-ru,VS.90).gifПримечание.

Дополнительные сведения об управлении состоянием и о возможностях, которые можно использовать для хранения сведений в веб-приложении, см. в разделах Общие сведения об управлении состоянием ASP.NET и Рекомендации по управлению состоянием ASP.NET.

Хотя файлы Cookie потенциально очень полезны в приложении, приложение не должно зависеть от возможности хранить файлы Cookie. Не следует использовать файлы Cookie для поддержки важных возможностей. Если приложение должно полагаться на файлы Cookie, то можно выполнить проверку, чтобы увидеть, примет ли их обозреватель. См. подраздел "Проверка принятия обозревателем файлов Cookie" далее в этом разделе.

Обозреватель отвечает за управление файлами Cookie в системе пользователя. Файлы Cookie отправляются обозревателю с помощью объекта HttpResponse, который предоставляет коллекцию с именем Cookies. Получить доступ к объекту HttpResponse можно как к свойству Response класса Page. Все файлы Cookie, которые необходимо отправить обозревателю, должны быть добавлены в эту коллекцию. При создании файла Cookie нужно задать имя Name и значение Value. Каждый файл Cookie должен иметь уникальное имя, чтобы позже при считывании его из обозревателя его можно было идентифицировать. Поскольку файлы Cookie сохраняются по имени, одинаковое именование двух файлов Cookie приведет к перезаписи одного из них.

Также можно задать дату и время окончания срока действия для файла Cookie. Файлы Cookie с истекшим сроком действия удаляются обозревателем при посещении пользователем создавшего их веб-узла. Следует задавать срок действия файла Cookie, пока приложение рассматривает значение файла Cookie действительным. Чтобы файл Cookie был практически "вечным", можно задать дату окончания срока действия через 50 лет.

ms178194.alert_note(ru-ru,VS.90).gifПримечание.

Пользователи могут удалить файлы Cookie с компьютера в любой момент. Даже если для хранения файлов Cookie был установлен долгий срок действия, пользователь может решить удалить все файлы Cookie, удалив все параметры, которые, возможно, были в них сохранены.

Если окончание срока действия для файла Cookie не задается, то файл Cookie создается, но не сохраняется на жестком диске пользователя. Вместо этого, файл Cookie поддерживается как часть сведений сеанса пользователя. При закрытии пользователем обозревателя файл Cookie удаляется. Такие непостоянные файлы Cookie полезны для сведений, которые необходимо сохранить только в течение короткого промежутка времени, или для сведений, которые из соображений безопасности не следует записывать на диск на клиентском компьютере. Например, непостоянные файлы Cookie полезны, если пользователь работает на общедоступном компьютере, на котором не нужно записывать файл Cookie на диск.

Файлы Cookie можно добавить к коллекцию Cookies несколькими способами. В следующем примере показаны два метода записи файлов Cookie:

Response.Cookies("userName").Value = "patrick"
Response.Cookies("userName").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("lastVisit")
aCookie.Value = DateTime.Now.ToString()
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)
Response.Cookies["userName"].Value = "patrick";
Response.Cookies["userName"].Expires = DateTime.Now.AddDays(1);

HttpCookie aCookie = new HttpCookie("lastVisit");
aCookie.Value = DateTime.Now.ToString();
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);

В данном примере в коллекцию Cookies добавляются два файла cookie, один с именем userName и второй с именем lastVisit. Для первого файла Cookie значения коллекции Cookies задаются напрямую. Добавить значения в коллекцию можно таким образом, поскольку Cookies является производным специализированной коллекции типа NameObjectCollectionBase.

Для второго файла Cookie код создает экземпляр объекта типа HttpCookie, задает его свойства и затем добавляет его в коллекцию Cookies используя метода Add. При создании экземпляра объекта HttpCookie необходимо передать имя файла Cookie в составе конструктора.

Оба примера выполняют одну и ту же задачу: запись файла Cookie в обозреватель. В обоих методах значение срока действия должно быть типа DateTime. Однако значение lastVisited также является значением даты и времени. Поскольку все значения файлов Cookie хранятся в виде строк, значение даты и времени должно быть преобразовано в String.

В файле Cookie можно хранить одно значение, например, имя пользователя и последнее посещение. Также в одном файле Cookie можно хранить несколько пар "имя-значение". Эти пары называются подразделами. (структура подразделов очень похожа на структуру строки запроса в URL-адресе). Например, вместо создания двух отдельных файлов Cookie с именами userName и lastVisit можно создать один файл Cookie с именем userInfo, в котором есть подразделы userName и lastVisit.

Есть несколько аргументов в пользу использования подразделов. Во-первых, удобно помещать связанную информацию в одном файле Cookie. Кроме того, поскольку вся информация находится в одном файле Cookie, то атрибуты Cookie, такие как срок действия, применяются ко всей информации. (и наоборот, если необходимо присвоить разные даты окончания срока действия разным типам информации, то информацию следует хранить в разных файлах Сookie.)

Также файл Cookie с подразделами помогает в ограничении размера файлов Cookie. Как отмечалось ранее в подразделе "Ограничения файлов Сookie", размер файлов Сookie обычно ограничен 4096 байтами и нельзя сохранить более 20 файлов Сookie с одного веб-узла. При использовании одного файла Cookie с подразделами используется меньше тех выделенных веб-узлу 20 файлов Cookie. Кроме того, в файле Cookie около 50 знаков отводится системной информации (информация о сроке действия и т. д.), плюс длина сохраненного в нем значения, и все это приближает размер файла к лимиту в 4096 байт. При сохранении пяти подразделов вместо пяти отдельных файлов Cookie можно сократить вычислительные затраты на обработку отдельных файлов Cookie и сэкономить приблизительно 200 байт.

Для создания файла Cookie с подразделами можно использовать вариант синтаксиса для записи одного файла Cookie. В следующем примере показаны два способа записи одного файла Сookie, в каждом из которых два подраздела:

Response.Cookies("userInfo")("userName") = "patrick"
Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString()
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("userInfo")
aCookie.Values("userName") = "patrick"
aCookie.Values("lastVisit") = DateTime.Now.ToString()
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)
Response.Cookies["userInfo"]["userName"] = "patrick";
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);

HttpCookie aCookie = new HttpCookie("userInfo");
aCookie.Values["userName"] = "patrick";
aCookie.Values["lastVisit"] = DateTime.Now.ToString();
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);

По умолчанию все файлы Cookie для веб-узла хранятся вместе на клиенте и все они отправляются серверу с любым запросом к этому веб-узел. Другими словами, каждая страница на веб-узле получает все файлы Cookie для этого веб-узла. Однако область файлов Cookie можно задать двумя способами:

  • Ограничьте область файлов Cookie до папки на сервере, что позволит ограничить файлы Cookie до приложения на веб-узле.

  • Задайте как область домен, что позволит указать, какие поддомены в домене могут иметь доступ к файлу Cookie.

Чтобы ограничить файлы Cookie до папки на сервере, присвойте значение свойству файла Сookie Path, как показано в следующем примере:

Dim appCookie As New HttpCookie("AppCookie")
appCookie.Value = "written " & DateTime.Now.ToString()
appCookie.Expires = DateTime.Now.AddDays(1)
appCookie.Path = "/Application1"
Response.Cookies.Add(appCookie)
HttpCookie appCookie = new HttpCookie("AppCookie");
appCookie.Value = "written " + DateTime.Now.ToString();
appCookie.Expires = DateTime.Now.AddDays(1);
appCookie.Path = "/Application1";
Response.Cookies.Add(appCookie);
ms178194.alert_note(ru-ru,VS.90).gifПримечание.

Также можно записать файлы Cookie путем прямого их добавления в коллекцию Cookies, как показано в предыдущих примерах.

Путем может быть физический путь в корневом каталоге веб-узла или виртуальный путь. В результате этого файл Cookie будет доступен только страницам в папке Application1 или виртуальному корню. Например, если веб-узел называется www.contoso.com, то файл Cookie, созданный в предыдущем примере, будет доступен страницам с указанным путем https://www.contoso.com/Application1/ и любым страницам в этой папке. Однако файл Cookie не будет доступен страницам в других приложениях, например, https://www.contoso.com/Application2/ или просто https://www.contoso.com/.

ms178194.alert_note(ru-ru,VS.90).gifПримечание.

В некоторых обозревателях при вводе пути учитывается регистр символов. Невозможно контролировать, как пользователи вводят URL-адреса в обозревателях, но, если приложение зависит от файлов Cookie, привязанных к определенному пути, убедитесь, что URL-адреса в создаваемых гиперссылках соответствуют регистру значения свойства Path.

По умолчанию файлы Cookie связаны с определенным доменом. Например, если веб-узлом является узел www.contoso.com, то создаваемые файлы Cookie отправляются серверу при запросе пользователями любой страницы с этого веб-узла. (сюда могут не входить файлы Cookie с определенным значением пути). Если на веб-узле есть поддомены — например, contoso.com, sales.contoso.com и support.contoso.com — то файлы Cookie можно связать с определенным поддоменом. Для этого необходимо присвоить свойству Cookie Domain значение, как показано в следующем примере:

Response.Cookies("domain").Value = DateTime.Now.ToString()
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "support.contoso.com"
Response.Cookies["domain"].Value = DateTime.Now.ToString();
Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1);
Response.Cookies["domain"].Domain = "support.contoso.com";

Если домен настроен таким образом, файл Сookie будет доступен только страницам в определенном поддомене. Также можно использовать свойство Domain для создания файла Сookie, который можно было бы совместно использовать несколькими поддоменами, как показано в следующем примере:

Response.Cookies("domain").Value = DateTime.Now.ToString()
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "contoso.com"
Response.Cookies["domain"].Value = DateTime.Now.ToString();
Response.Cookies["domain"].Expires = DateTime.Now.AddDays(1);
Response.Cookies["domain"].Domain = "contoso.com";

При таком подходе файл Сookie будет доступен основному домену, а так же доменам sales.contoso.com и support.contoso.com.

Считывание файлов Сookie

При выполнении обозревателем запроса к серверу он отправляет файлы Сookie этому серверу вместе с запросом. В приложениях ASP.NET можно считывать файлы Сookie путем использования объекта HttpRequest, доступного в виде свойства Request класса Page. Структура объекта HttpRequest по сути такая же, как структура объекта HttpResponse, так что можно считывать файлы Сookie из объекта HttpRequest практически так же, как файлы Сookie были записаны в объект HttpResponse. В следующем примере показаны два способа получения значения из файла Сookie с именем username и отображения этого значения в элементе управления Label:

If Not Request.Cookies("userName") Is Nothing Then
    Label1.Text = Server.HtmlEncode(Request.Cookies("userName").Value)
End If

If Not Request.Cookies("userName") Is Nothing Then
    Dim aCookie As HttpCookie = Request.Cookies("userName")
    Label1.Text = Server.HtmlEncode(aCookie.Value)
End If
if(Request.Cookies["userName"] != null)
    Label1.Text = Server.HtmlEncode(Request.Cookies["userName"].Value);

if(Request.Cookies["userName"] != null)
{
    HttpCookie aCookie = Request.Cookies["userName"];
    Label1.Text = Server.HtmlEncode(aCookie.Value);
}

Перед попыткой получения значения из файла Сookie следует убедиться в существовании файла Сookie; если файл Сookie не существует, то возникнет исключение NullReferenceException. Также обратите внимание, что метод HtmlEncode был вызван для кодирования содержимого файла Сookie перед его отображением на странице. Это гарантирует, что пользователь-злоумышленник не добавил исполняемый сценарий в файл Сookie. Дополнительные сведения о безопасности файлов Сookie см. в подразделе "Файлы Сookie и безопасность".

ms178194.alert_note(ru-ru,VS.90).gifПримечание.

Поскольку разные обозреватели по-разному сохраняют файлы Сookie, на одном компьютере разные обозреватели не обязательно смогут прочесть файлы Сookie друг друга. Например, при использовании в первый раз веб-обозревателя Internet Explorer для проверки страницы, но при следующем использовании другого обозревателя для повторной проверки, второй обозреватель не найдет файлы Сookie, сохраненные веб-обозревателем Internet Explorer.

Считывание значения подраздела в файле Сookie аналогично его заданию. Код в следующем примере показывает один из способов получения значения подраздела:

If Not Request.Cookies("userInfo") Is Nothing Then
    Label1.Text = _
        Server.HtmlEncode(Request.Cookies("userInfo")("userName"))
    Label2.Text = _
        Server.HtmlEncode(Request.Cookies("userInfo")("lastVisit"))
End If
if(Request.Cookies["userInfo"] != null)
{
    Label1.Text = 
        Server.HtmlEncode(Request.Cookies["userInfo"]["userName"]);

    Label2.Text =
        Server.HtmlEncode(Request.Cookies["userInfo"]["lastVisit"]);
}

В предыдущем примере код считывает значение подраздела lastVisit, которое ранее было задано как строковое представление значения DateTime. Файлы Сookie хранят значения как строки, так что если нужно использовать значение lastVisit как дату, то необходимо преобразовать его в соответствующий тип, как в этом примере:

Dim dt As DateTime
dt = DateTime.Parse(Request.Cookies("userInfo")("lastVisit"))
DateTime dt;
dt = DateTime.Parse(Request.Cookies["userInfo"]["lastVisit"]);

Подразделы в файле Cookie определены как коллекция типа NameValueCollection. Следовательно, еще одним способом получения отдельного подраздела является получение коллекции подразделов и последующее извлечение значения подраздела по имени, как показано в следующем примере:

If Not Request.Cookies("userInfo") Is Nothing Then
    Dim UserInfoCookieCollection As _
        System.Collections.Specialized.NameValueCollection
    UserInfoCookieCollection = Request.Cookies("userInfo").Values
    Label1.Text = _
        Server.HtmlEncode(UserInfoCookieCollection("userName"))
    Label2.Text = _
        Server.HtmlEncode(UserInfoCookieCollection("lastVisit"))
End If
if(Request.Cookies["userInfo"] != null)
{
    System.Collections.Specialized.NameValueCollection
        UserInfoCookieCollection;
       
    UserInfoCookieCollection = Request.Cookies["userInfo"].Values;
    Label1.Text = 
        Server.HtmlEncode(UserInfoCookieCollection["userName"]);
    Label2.Text =
        Server.HtmlEncode(UserInfoCookieCollection["lastVisit"]);
}

Обозреватель отвечает за управление файлами Cookie, а срок действия файла Cookie помогает обозревателю управлять их хранением. Следовательно, хотя можно считать имя и значение файла Cookie, невозможно считать дату и время окончания срока действия. При отправке обозревателем информации о файле Сookie на сервер, обозреватель не включает информацию о сроке действия. (свойство Expires Сookie всегда возвращает нулевое значение даты-времени). Если срок действия файла Сookie является важным фактором, то необходимо его сбросить — это рассматривается в подразделе "Изменение и удаление файлов Сookie".

ms178194.alert_note(ru-ru,VS.90).gifПримечание.

Можно считать свойство Expires Cookie, заданное в объекте HttpResponse перед отправкой файла Cookie обозревателю. Но получить обратно срок действия в объекте HttpRequest все же не удастся.

Считывание коллекций файлов Сookie

Иногда может возникнуть необходимость в считывании данных из всех файлов Сookie, доступных странице. Чтобы считать имена и значения всех файлов Сookie, доступных странице, можно просмотреть коллекцию Cookies путем использования кода, например, следующего.

Dim i As Integer
Dim output As System.Text.StringBuilder = New System.Text.StringBuilder
Dim aCookie As HttpCookie
For i = 0 to Request.Cookies.Count - 1
    aCookie = Request.Cookies(i)
    output.Append("Cookie name = " & Server.HtmlEncode(aCookie.Name) _
        & "<br />")
    output.Append("Cookie value = " & _
        Server.HtmlEncode(aCookie.Value) & "<br /><br />")
Next
Label1.Text = output.ToString()
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie aCookie;
for(int i=0; i<Request.Cookies.Count; i++)
{
    aCookie = Request.Cookies[i];
    output.Append("Cookie name = " + Server.HtmlEncode(aCookie.Name) 
        + "<br />");
    output.Append("Cookie value = " + Server.HtmlEncode(aCookie.Value)
        + "<br /><br />");
}
Label1.Text = output.ToString();
ms178194.alert_note(ru-ru,VS.90).gifПримечание.

При выполнении этого кода, возможно, обнаружится файл Сookie с именем ASP.NET_SessionId. Это файл Сookie, используемый ASP.NET для хранения уникального идентификатора для сеанса. Файл Сookie сеанса не сохраняется на жестком диске. Дополнительные сведения о файлах Сookie сеанса см. в подразделе "Файлы cookie и состояние сеанса" далее в этом разделе.

Ограничение предыдущего примера заключается в том, что если у файла Сookie есть подразделы, то они будут отображены как единая строка имени-значения. Свойство HasKeys Cookie можно считать для определения наличия подразделов в файле Cookie. Если подразделы есть, то можно считать коллекцию подразделов для получения отдельных имен и значений подраздела. Можно считать значения подразделов в коллекции Values непосредственно по значению индекса. Соответствующие имена подразделов доступны в члене AllKeys коллекции Values, возвращающей массив строк. Также возможно использование члена Keys коллекции Values. Однако свойство AllKeys кэшируется при первом доступе к нему. Напротив, свойство Keys строит массив при каждом доступе к нему. По этой причине свойство AllKeys намного более быстро при последующих доступах в контексте запроса одной и той же страницы.

В следующем примере показано изменение предыдущего примера. Свойство HasKeys используется для проверки подразделов и при обнаружении подразделов пример получает подразделы из коллекции Values.

Dim i As Integer
Dim j As Integer
Dim output As System.Text.StringBuilder = New StringBuilder()
Dim aCookie As HttpCookie
Dim subkeyName As String
Dim subkeyValue As String
For i = 0 To Request.Cookies.Count - 1
    aCookie = Request.Cookies(i)
    output.Append("Name = " & aCookie.Name & "<br />")
    If aCookie.HasKeys Then
        For j = 0 To aCookie.Values.Count - 1
            subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys(j))
            subkeyValue = Server.HtmlEncode(aCookie.Values(j))
            output.Append("Subkey name = " & subkeyName & "<br />")
            output.Append("Subkey value = " & subkeyValue & _
                "<br /><br />")
        Next
    Else
        output.Append("Value = " & Server.HtmlEncode(aCookie.Value) & _
            "<br /><br />")
    End If
Next
Label1.Text = output.ToString()
for(int i=0; i<Request.Cookies.Count; i++)
{
    aCookie = Request.Cookies[i];
    output.Append("Name = " + aCookie.Name + "<br />");
    if(aCookie.HasKeys)
    {
        for(int j=0; j<aCookie.Values.Count; j++)
        {
            subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys[j]);
            subkeyValue = Server.HtmlEncode(aCookie.Values[j]);
            output.Append("Subkey name = " + subkeyName + "<br />");
            output.Append("Subkey value = " + subkeyValue + 
                "<br /><br />");
        }
    }
    else
    {
        output.Append("Value = " + Server.HtmlEncode(aCookie.Value) +
            "<br /><br />");
    }
}
Label1.Text = output.ToString();

В качестве альтернативы можно извлечь подразделы как объект NameValueCollection, как показано в следующем примере:

Dim i As Integer
Dim j As Integer
Dim output As System.Text.StringBuilder = New StringBuilder()
Dim aCookie As HttpCookie
Dim subkeyName As String
Dim subkeyValue As String
For i = 0 To Request.Cookies.Count - 1
    aCookie = Request.Cookies(i)
    output.Append("Name = " & aCookie.Name & "<br />")
    If aCookie.HasKeys Then
        Dim CookieValues As _
            System.Collections.Specialized.NameValueCollection = _
                aCookie.Values
        Dim CookieValueNames() As String = CookieValues.AllKeys
        For j = 0 To CookieValues.Count - 1
            subkeyName = Server.HtmlEncode(CookieValueNames(j))
            subkeyValue = Server.HtmlEncode(CookieValues(j))
            output.Append("Subkey name = " & subkeyName & "<br />")
            output.Append("Subkey value = " & subkeyValue & _
                "<br /><br />")
        Next
    Else
        output.Append("Value = " & Server.HtmlEncode(aCookie.Value) & _
            "<br /><br />")
    End If
Next
Label1.Text = output.ToString
System.Text.StringBuilder output = new System.Text.StringBuilder();
HttpCookie aCookie;
string subkeyName;
string subkeyValue;

for (int i = 0; i < Request.Cookies.Count; i++)
{
    aCookie = Request.Cookies[i];
    output.Append("Name = " + aCookie.Name + "<br />");
    if (aCookie.HasKeys)
    {
        System.Collections.Specialized.NameValueCollection CookieValues = 
            aCookie.Values;
        string[] CookieValueNames = CookieValues.AllKeys;
        for (int j = 0; j < CookieValues.Count; j++)
        {
            subkeyName = Server.HtmlEncode(CookieValueNames[j]);
            subkeyValue = Server.HtmlEncode(CookieValues[j]);
            output.Append("Subkey name = " + subkeyName + "<br />");
            output.Append("Subkey value = " + subkeyValue + 
                "<br /><br />");
        }
    }
    else
    {
        output.Append("Value = " + Server.HtmlEncode(aCookie.Value) +
            "<br /><br />");
    }
}
Label1.Text = output.ToString();

Невозможно прямое изменение файла Cookie. Вместо этого, изменение файла Cookie состоит в создании нового файла Cookie с новыми значениями и последующей отправке файла Cookie обозревателю для перезаписи старой версии на клиенте. В следующем примере показано, как изменить значение файла Сookie, хранящего количество посещений веб-узла пользователем:

Dim counter As Integer
If Request.Cookies("counter") Is Nothing Then
    counter = 0
Else
    counter = Int32.Parse(Request.Cookies("counter").Value)
End If
counter += 1
Response.Cookies("counter").Value = counter.ToString
Response.Cookies("counter").Expires = DateTime.Now.AddDays(1)
int counter;
if (Request.Cookies["counter"] == null)
    counter = 0;
else
{
    counter = int.Parse(Request.Cookies["counter"].Value);
}
counter++;

Response.Cookies["counter"].Value = counter.ToString();
Response.Cookies["counter"].Expires = DateTime.Now.AddDays(1);

Удаление файлов Сookie

Удаление файла Cookie, т. е. физическое удаление его с жесткого диска пользователя это частный случай его изменения. Невозможно прямо удалить файл Cookie, поскольку он находится на компьютере пользователя. Однако можно сделать так, чтобы обозреватель удалил файл Cookie. Методика заключается в создании нового файла Cookie с тем же именем, что и файл, который требуется удалить, и в задании даты окончания срока действия файла Cookie ранее, чем сегодняшняя дата. При проверке обозревателем срока действия файла Cookie обозреватель удалит только что устаревший файл Cookie. Следующий пример кода демонстрирует один способ удаления всех файлов Cookie, доступных приложению.

Dim aCookie As HttpCookie
Dim i As Integer
Dim cookieName As String
Dim limit As Integer = Request.Cookies.Count - 1
For i = 0 To limit
    cookieName = Request.Cookies(i).Name
    aCookie = New HttpCookie(cookieName)
    aCookie.Expires = DateTime.Now.AddDays(-1)
    Response.Cookies.Add(aCookie)
Next
HttpCookie aCookie;
string cookieName;
int limit = Request.Cookies.Count;
for (int i=0; i<limit; i++)
{
    cookieName = Request.Cookies[i].Name;
    aCookie = new HttpCookie(cookieName);
    aCookie.Expires = DateTime.Now.AddDays(-1);
    Response.Cookies.Add(aCookie);
}

Изменение или удаление подразделов

Изменение отдельного подраздела такое же, как его создание, как показано в следующем примере:

Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString()
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)
Response.Cookies["userInfo"]["lastVisit"] = DateTime.Now.ToString();
Response.Cookies["userInfo"].Expires = DateTime.Now.AddDays(1);

Для удаления отдельного подраздела необходимо использование коллекции Values Сookie, которая содержит подразделы. Сначала необходимо воссоздать файл Cookie, получив его из объекта Cookies. Затем можно вызвать метод Remove коллекцииValues, передав методу Remove имя подраздела, который необходимо удалить. Затем необходимо добавить файл Сookie в коллекцию Cookies, чтобы он был отправлен в измененной форме обратно обозревателю. В следующем примере демонстрируется удаление подраздела. В примере имя удаляемого подраздела указано в переменной.

Dim subkeyName As String
subkeyName = "userName"
Dim aCookie As HttpCookie = Request.Cookies("userInfo")
aCookie.Values.Remove(subkeyName)
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)
string subkeyName;
subkeyName = "userName";
HttpCookie aCookie = Request.Cookies["userInfo"];
aCookie.Values.Remove(subkeyName);
aCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(aCookie);

Вопросы безопасности, связанные с файлами Сookie, аналогичны вопросам, связанным с получением данных от клиента. В приложении файлы Cookie являются еще одной формой пользовательского ввода, а значит, их можно просмотреть или подделать. Пользователь может как минимум увидеть данные, хранимые в файле Cookie, так как файл Cookie доступен на компьютере пользователя. Также пользователь может изменить файл Cookie перед отправкой его обозревателем.

Нельзя хранить в файле Cookie конфиденциальные данные, например, имена пользователей, пароли, номера кредитных карт и т. д. Не помещайте в файл cookie того, что не должно попасть в руки пользователю или кому-нибудь, кто может каким-либо образом украсть файл Сookie.

Аналогично, не следует полностью доверять данным, хранящимся в файле Cookie. Не следует предполагать, что данные не изменятся со времени их создания; используйте те же меры предосторожности при работе со значениями файла Cookie, какие использовались бы при работе с данными, введенными пользователем на веб-странице. Предыдущие примеры в этом разделе продемонстрировали HTML-кодирование содержимого файла Сookie перед отображением значения на странице, так же как перед отображением любой информации, полученной от пользователей.

Файлы Cookie пересылаются между обозревателем и сервером в виде обычного текста и любой, кто может перехватить ваш веб-трафик, сможет прочесть файл Cookie. Можно задать свойство для файла Cookie, которое приведет к пересылке файла Сookie только в том случае, если подключение использует протокол SSL. Протокол SSL не защищает файл Cookie от прочтения или обработки, пока он находится на компьютере пользователя, но он предупреждает прочтение файла Cookie во время его передачи, так как файл Cookie является зашифрованным. Дополнительные сведения см. в разделе Основные методы обеспечения безопасности веб-приложений.

Пользователи могут настроить обозреватели на отказ от файлов cookie. Ошибка не возникнет, если файл Сookie не может быть записан. Аналогично обозреватель не отправляет информацию серверу о своей политике в отношении файлов Cookie.

ms178194.alert_note(ru-ru,VS.90).gifПримечание.

Свойство Cookies не указывает, включены ли файлы Cookie. Оно лишь указывает, поддерживает ли в принципе текущий обозреватель файлы Сookie.

Одним способом определения принятия файлов Cookie является попытка записи файла Сookie, а затем попытка считывания его. Если невозможно считать записанный файл Cookie, предполагается, что поддержка файлов Cookie отключена в обозревателе.

В следующем примере кода представлен способ проверки принятия файлов Cookie. Пример состоит из двух страниц. Первая страница записывает файл Сookie, а затем перенаправляет обозреватель на вторую страницу. Вторая страница пытается считать файл Сookie. Она, в свою очередь, перенаправляет обозреватель обратно на первую страницу, добавляя к URL-адресу переменную строки запроса с результатами проверки.

Код для первой страницы выглядит следующим образом:

Protected Sub Page_Load(ByVal sender As Object, _
        ByVal e As EventArgs) Handles Me.Load
    If Not Page.IsPostBack Then
        If Request.QueryString("AcceptsCookies") Is Nothing Then
            Response.Cookies("TestCookie").Value = "ok"
            Response.Cookies("TestCookie").Expires = _
                DateTime.Now.AddMinutes(1)
            Response.Redirect("TestForCookies.aspx?redirect=" & _
                Server.UrlEncode(Request.Url.ToString))
        Else
            Label1.Text = "Accept cookies = " & _
                Server.UrlEncode(Request.QueryString("AcceptsCookies"))
        End If
    End If
End Sub
protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        if (Request.QueryString["AcceptsCookies"] == null)
        {
            Response.Cookies["TestCookie"].Value = "ok";
            Response.Cookies["TestCookie"].Expires =
                DateTime.Now.AddMinutes(1);
            Response.Redirect("TestForCookies.aspx?redirect=" +
                Server.UrlEncode(Request.Url.ToString()));
        }
        else
        {
            Label1.Text = "Accept cookies = " +
                Server.UrlEncode(
                Request.QueryString["AcceptsCookies"]);
        }
    }
}

Страница сначала выполняет проверку, чтобы увидеть, является ли это обратной передачей, и, если нет, то страница выполняет поиск имени переменной строки запроса AcceptsCookies, содержащей результаты проверки. Если переменная строки запроса отсутствует, то проверка не завершена, так что код записывает файл Cookie с именем TestCookie. После записи файла Cookie пример вызывает Redirect для перехода на тестовую страницу TestForCookies.aspx. К URL-адресу тестовой страницы добавляется переменная строки запроса с именем redirect, содержащая URL-адрес текущей страницы; это позволит выполнять перенаправление обратно на эту страницу после выполнения проверки.

Тестовая страница может состоять полностью из кода; нет необходимости, чтобы она содержала элементы управления. В следующем примере кода показана тестовая страница.

Sub Page_Load()
    Dim redirect As String = Request.QueryString("redirect")
    Dim acceptsCookies As String
    If Request.Cookies("TestCookie") Is Nothing Then
        acceptsCookies = "no"
    Else
        acceptsCookies = "yes"
        ' Delete test cookie.
        Response.Cookies("TestCookie").Expires = _
            DateTime.Now.AddDays(-1)
    End If
    Response.Redirect(redirect & "?AcceptsCookies=" & acceptsCookies, _
       True)
End Sub
protected void Page_Load(object sender, EventArgs e)
{
    string redirect = Request.QueryString["redirect"];
    string acceptsCookies;
    if(Request.Cookies["TestCookie"] ==null)
        acceptsCookies = "no";
    else
    {
        acceptsCookies = "yes";
        // Delete test cookie.
        Response.Cookies["TestCookie"].Expires = 
            DateTime.Now.AddDays(-1);
    }
    Response.Redirect(redirect + "?AcceptsCookies=" + acceptsCookies,
    true);
}

После считывания переменной перенаправления строки запроса код попытается считать файл Cookie. В целях обслуживания если файл Сookie существует, то он сразу же будет удален. После завершения проверки код создаст новый URL-адрес из URL-адреса, переданного ему в переменной строки запроса redirect. Новый URL-адрес также содержит переменную строки запроса, содержащую результаты проверки. Последним шагом является использование нового URL-адреса для перенаправления обозревателя на исходную страницу.

Преимуществом в примере является сохранение результатов проверки файла Cookie в постоянном хранилище, например, в базе данных, чтобы не было необходимости повторять проверку при каждом просмотре пользователем исходной страницы. (для сохранения результатов проверки в состоянии сеанса по умолчанию требуются файлы Cookie).

При переходе пользователя на веб-узел сервер устанавливает для этого пользователя уникальный сеанс, который длится на протяжении всего посещения пользователя. Для каждого сеанса ASP.NET поддерживает информацию о состоянии сеанса, где приложения могут сохранять информацию, связанную с работой пользователя. Дополнительные сведения см. в разделе Общие сведения о состоянии сеанса ASP.NET.

ASP.NET должен отслеживать идентификатор сеанса для каждого пользователя, чтобы была возможность сопоставлять пользователя с информацией о состоянии сеанса на сервере. По умолчанию ASP.NET использует непостоянный файл Cookie для хранения состояния сеанса. Однако в случае отключения пользователем файлов Сookie в обозревателе информацию о состоянии сеанса нельзя хранить в файле Cookie.

ASP.NET предлагает альтернативу в форме сеансов без поддержки файлов Cookie. Можно настроить приложение на сохранение идентификаторов сеансов не в файле Cookie, а в URL-адресах страниц на веб-узле. Если приложение полагается на состояние сеанса, то можно рассмотреть настройку его на использование сеансов без поддержки файлов Сookie. Однако в некоторых случаях, если пользователь совместно использует URL-адрес с кем-нибудь другим — возможно, для отправки URL-адреса коллеге пока сеанс пользователя еще активен — тогда оба пользователя могут в конечном счете совместно использовать один сеанс с непредсказуемыми результатами. Дополнительные сведения о настройке приложения на использования сеансов без поддержки файлов Cookie см. в разделе Общие сведения об управлении состоянием ASP.NET.

К началу

Примеры кода

Примеры использования

Управление состоянием приложения

Практические и пошаговые руководства

Практическое руководство. Настройка файлов Cookie проверки подлинности службы проверки подлинности WCF

К началу

Ссылки на классы

HttpCookie

Предоставляет надежный способ создания и использования отдельных файлов НТТР Сookie.

Cookies

Получает коллекцию ответов файлов Сookie.

Cookies

Получает коллекцию файлов Cookie, отправленных клиентом.

К началу

Дополнительные источники

К началу

Новые возможности

К началу

См. также

Основные понятия

Общие сведения об управлении состоянием ASP.NET

Ссылки

К началу