Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lab4.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.32 Mб
Скачать

Лабораторная работа № 4. Управление состоянием в asp.Net

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

В ASP.NET существует два типа управления состоянием: на клиенте и на сервере. При управлении состоянием на клиенте сведения о пользователе хранятся на компью­тере клиента и передаются коду веб-страницы через строку запроса или cookie-файлы. При управлении состоянием на сервере пользователей отслеживают также по URL или cookie, но сведения о них хранятся в памяти сервера или в базе данных.

4.1. Управление состоянием на клиенте

Управление состоянием путем хранения данных состояния на клиенте характеризуется максимальной масштабируемостью. В ASP.NET существует несколько методов хране­ния на клиенте сведений, необходимых для управления состоянием:

  • состояние отображения (view state).

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

  • состояние элемента управления (control state).

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

  • скрытые поля (hidden fields).

С помощью скрытых полей данные сохраняются в HTML-форме и не отображаются в браузере. Данные становятся доступными после обработки формы.

  • cookie-файлы.

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

  • строки запроса (query strings).

Строки запроса сохраняют значения в составе URL, поэтому значения видимы для пользователя. Применяются для отправки состояния через электронную почту либо мгновенно — через URL.

Выбор способа управления состоянием

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

Рис. 1. При управлении состоянием на клиенте данные состояния хранятся на клиентском компьютере, а при управлении состоянием на сервере — на серверной машине

Хранение информации на клиенте имеет следующие преимущества:

  • лучшая масштабируемость.

При управлении состоянием на сервере каждый подключившийся к веб-серверу кли­ент занимает часть ресурсов сервера. Если сайт одновременно посещают сотни и тысячи пользователей, для хранения их состояния им потребуется много памяти, которая может стать узким местом. Устранить его можно, переложив управление дан­ными состояния на пользователей;

  • поддержка множества веб-серверов.

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

Хранение информации на сервере имеет следующие преимущества:

  • безопасность.

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

  • снижение нагрузки на сеть.

При транспортировке больших объемов данных состояния между клиентом и сер­вером создается значительная нагрузка на канал связи и увеличивается время заг­рузки страницы, что чревато ростом расходов и снижением масштабируемости. Пересылка больших объемов данных негативно сказывается на эффективности мобильных клиентов, обычно подключенных через медленные каналы связи. Сле­довательно, громоздкую информацию управления состоянием (более 1 Кб) лучше хранить на сервере.

Состояние отображения ViewState

Несложно заметить, что после щелчка кнопки Submit на странице ASP.NET сохраняют­ся все значения и настройки. Например, если изменить текст и щелкнуть кнопку Submit, внесенные изменения будут отображаться и после перезагрузки страницы. Это проис­ходит благодаря наличию в ASP.NET поддержки управления состоянием на клиенте с помощью свойства ViewState, которое содержит объект-словарь, сохраняющий значения между запросами страницы. После обработки страницы ASP.NET ее текущее состоя­ние, а также элементов управления хэшируется и строка с хэшем сохраняется в скрытом поле страницы. Если данные получаются очень объемными и не помещаются в един­ственном поле (это зависит от значения свойства MaxPageStateFieldLength), ASP.NET «режет» состояние отображения на части и записывает его в несколько скрытых полей. В следующем примере кода показано сохранение состояния отображения в виде скры­той формы среди HTML-кода страницы:

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTIxNDIyOTM0Mg9kFgICAw9kFgICAQ8PFgIeBFRleHQFEzQvNS8yMDA2IDE6Mzc6MTEgUE1kZGROWHn/rt75XF/pMGnqjqHlH66cdw==" />

Шифрование состояния отображения

Чтобы затруднить злонамеренным пользователям доступ к состоянию отображения, сле­дует включить его шифрование. Это необходимо, если в состоянии отображения плани­руется хранить конфиденциальную информацию, но шифрование увеличивает издерж­ки веб-сервера на обработку. Чтобы включить шифрование состояния отображения в приложении, в файле Web.config присвойте атрибуту <pages viewStateEncryptionMode> значение Always:

<configuration>

<system.web>

<pages viewStateEncryptionMode="Always"/>

</system.web>

</configuration>

Можно включить шифрование состояния отображения только на заданной страни­це, установив соответствующее значение в директиве page, как показано в следующем примере:

<%@ Page Language="C#" AutoEventWireup=”true" CodeFile=”Default.aspx.cs" Inherits="_Default'’ ViewStateEncryptionMode="Always"%>

Так как объект ViewState поддерживает шифрование, он представляет собой самый безопасный метод управления состоянием на клиенте. Зашифрованные данные ViewState удовлетворяют большинству требований безопасности, но в любом случае безопаснее хранить состояние изображения на сервере.

Отключение ViewState

По умолчанию состояние отображения активно у каждого элемента управления, вклю­чая Label, которые почти никогда не изменяются. К сожалению, состояние отображе­ния увеличивает издержки по обработке форм ASP.NET. Чтобы отключить состояние отображения веб-элемента управления, присвойте его свойству EnableViewState значе­ние False. Это ускорит обработку данных на сервере и уменьшит размер страницы.

Чтение и запись данных ViewState

В объект ViewState можно добавлять пользовательские значения (а также извлекать их из него). Самым эффективным и безопасным способом мониторинга состояния какого- либо значения во время посещения пользователем одной веб-страницы ASP.NET явля­ется добавление этого значения в ViewState. Однако этот способ не работает на других веб-страницах, и потому ViewState полезен только для временного хранения значений.

Следующий пример кода показывает, как определить, записано ли время после­днего визита в ViewState, как вывести его в элементе управления Label с именем Label1 и присвоить значению текущее время. Для использования этого кода создайте форму, добавьте на нее элемент управления Label с именем Label1 и элемент управления Button:

//C#

// Проверить, существует ли объект ViewState, показать результат

if (ViewState["lastVisit"] != null)

Label1.Text = (string)ViewState["lastVisit"];

else

Label1.Text = "lastVisit ViewState not defined.";

// Объявить объект ViewState для следующего просмотра страницы

ViewState.Add("lastVisit", DateTime.Now.ToString());

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

//C#

// Проверить, существует ли объект ViewState, показать результат

if (ViewState["lastVisit"] != null)

Label1.Text = ((DateTime)ViewState["lastVisit"]).ToString();

else

Label1.Text = "lastVisit ViewState not defined.";

// Объявить объект ViewState для следующего просмотра страницы

ViewState["lastVisit"] = DateTime.Now;

Состояние элемента управления

Если созданному вами пользовательскому элементу управления требуется ViewState, дру­гие разработчики могут нарушить его работу, отключив ViewState для целой страницы. Разрешить эту проблему можно путем сохранения сведений о состоянии элемента уп­равления в свойстве ControlState. Оно позволяет сохранить информацию о свойствах за­данного элемента управления, и его нельзя отключить, подобно свойству ViewState. Что­бы применить состояние пользовательского элемента управления, нужно переопреде­лить метод OnInit, добавив в него вызов RegisterRequiresControlState во время инициали­зации, а также переопределить методы SaveControlState и LoadControlState.

ControlState не позволяет разработчику отключить ViewState для элемента управле­ния. Как правило, выбор способа использования элементов управления оставляют разработчикам. Если ваш элемент управления просто не работает без ViewState, необходи­мо задействовать ControlState.

Скрытые поля

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

Элемент управления HiddenField хранит единственную переменную в свойстве Value, он должен быть явно добавлен на страницу. Скрытые поля хранят информацию для одной страницы, поэтому бесполезно сохранять в них сеансовые данные. При исполь­зовании скрытых полей страницы должны отправляться на сервер с помощью НТТР- метода POST (по щелчку кнопки), а не HTTP GET (по щелчку ссылки). В отличие от состояния отображения, скрытые поля не поддерживают сжатие, шифрование, хэширо­вание и хранение по частям, и потому пользователи могут просматривать или изменять сохраненные в них данные.

Cookie-файлы

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

На рис. 2 показано, как используются cookie-файлы, веб-клиенты и серверы. Сна­чала (шаг 1) веб клиент запрашивает страницу с сервера. Поскольку он не посещал сер­вер ранее, у него нет cookie-файла для отправки. Поэтому веб-сервер включает в состав отклика (шаг 2) cookie. Далее веб-клиент отправляет cookie при каждом запросе любой из страниц с того же сервера (шаги 3, 4 и т.д.).

Рис. 2. Веб-серверы используют cookie, чтобы отслеживать веб-клиентов

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

Чтение и запись Cookie

Веб-приложение создает cookie, посылая их клиенту в заголовке HTTP-отклика. Далее веб-браузер отправляет те же cookie на сервер с каждым запросом.

Чтобы создать cookie, добавьте значение в Response.Cookies объект HttpCookieCollection. Для просмотра cookie, присланного веб-браузером, прочитайте значение Request.Cookies. Следующий пример кода (обработчика события Page_Load) демонстрирует установку и чтение значения cookie с именем «lastVisit», содержащее значение текущего времени. Если у пользователя cookie уже установлен, код отобразит время последнего посещения страницы пользователем в элементе управления Label1.

//C#

// Проверить, существует ли cookie, и показать результат

if (Request.Cookies["lastVisit"] != null)

// Закодировать cookie на случай атаки через клиентский сценарий

Label1.Text = Server.HtmlEncode(Request.Cookies["lastVisit"].Value);

else

Label1.Text = "No value defined";

// Установить cookie для следующего визита

Response.Cookies["lastVisit"].Value = DateTime.Now.ToString();

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

В этом примере показан простейший из распространенных способов создания cookie. Так­же можно создавать экземпляры класса HttpCookie и добавлять их в HttpCookieCollection.

Если при посещении пользователем страницы из предыдущего примера cookie еще не установлен, код покажет сообщение «No value defined». Если же обновить страницу, код покажет время первого посещения. Заметьте, что этот код задает свойство Expires для cookie. Когда требуется сохранить cookie между запусками браузера, необходимо определить свойство Expires, установив тем самым срок хранения cookie на клиенте. Если свойство Expires не установлено, cookie будет храниться в памяти, пока пользователь не закроет браузер.

Для удаления cookie нужно задать в качестве срока хранения дату из прошлого и перезаписать cookie. Непосредственное же удаление cookie невозможно, поскольку они хранятся на компьютере клиента.

Для устранение неполадок и просмотра cookie следует использовать Trace.axd.

Управление областью видимости cookie

Некоторые веб-сайты хранят в cookie-файлах конфиденциальную информацию, поэто­му отправлять их на другие сайты нежелательно. По умолчанию браузер не отправляет cookie на веб-сайт с иным хост-именем (ранее уязвимости зашиты позволяли атакую­щим «обмануть» браузер, предоставив ему cookie-файлы от другого сайта).

Можно управлять областью видимости cookies, сужая ее до заданной папки веб-сер­вера или расширяя до любого из серверов домена. Чтобы сузить область видимости cookie до папки, установите свойство Path, как показано в следующем примере:

//C#

Response.Cookies["lastVisit"].Value = DateTime.Now.ToString();

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

Response.Cookies["lastVisit"].Path = "/Application1";

С областью видимости, суженной до «/Application1», браузер отправляет cookie на любую из страниц в папке /Application1, но не на страницы из других папок, даже если последние находятся на том же сервере.

Чтобы расширить область видимости до целого домена, установите свойство Domain, как показано в следующем примере:

//C#

Response.Cookies["lastVisit"].Value = DateTime.Now.ToString();

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

Response.Cookies["lastVisit"].Domain = "contoso.com";

При назначении свойству Domain значения «Contoso.com» браузер будет отправлять cookie любому серверу домена contoso.com, например www.contoso.com, intranet.contoso.com или private.contoso.com. Также можно записать в свойство Domain полное хост-имя, сужающее область видимости cookie до заданного сервера.

Сохранение множества значений в cookie

В зависимости от версии браузера разрешается хранить до 20 cookie-файлов размером до 4 Кб для каждого сайта. Можно обойти это ограничение, записав несколько значе­ний в одном cookie, как показано в следующем коде:

//C#

Response.Cookies["info"]["visit"].Value = DateTime.Now.ToString(); Response.Cookies["info"]["firstName"].Value = "Tony";

Response.Cookies["info"]["border"].Value = "blue";

Response.Cookies["info"].Expires = DateTime.Now.AddDays(1);

Этот код посылает веб-браузеру cookie со значением:

(visit=4/5/2006 2:35:18 PM) (firstName=Tony) (border=blue)

Свойства Expires, Domain и Path действуют на все значения внутри cookie. С помо­щью Request.Cookies можно получать и устанавливать отдельные значения в cookie.

Строки запроса

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

http://support.microsoft.com/Default.aspx?kbid=315233

В этом примере URL идентифицирует страницу Default.aspx. Строка запроса (начи­нающаяся со знака вопроса «?») включает одиночный параметр «kbid» со значением «315233». Строки запроса могут содержать и несколько параметров. В следующем при­мере поискового запроса для сайта microsoft.com строка запроса определяет язык и кри­терии поиска.

http://search.microsoft.com/results.aspx?mkt=en-US&setlang=en- US&q=hello+world

Значения этой строки запроса можно извлечь из страницы ASP.NET с помощью объектов, перечисленных в табл. 1.

Табл. 1. Пример значений строки запроса

Имя

Объект ASP.NET

Значение

mkt

Request.QueryString["mkt"]

en-US

setlang

Request.QueryString["setlang"]

en-US

q

Request.QueryString["q"]

hello world

Строки запроса — простой, но ограниченный механизм хранения информации о состоянии между запросами страниц. Например, в строке запроса легко передать коли­чество товара со страницы описания на страницу оформления заказа. Некоторые брау­зеры и устройства ограничивают длину URL 2083 символами. Другое ограничение со­стоит в необходимости отправки страницы командой НТТР GЕТ, чтобы значения из строки запроса были доступны для обработки. Следовательно, запросы нельзя добав­лять в целевые URL кнопок на формах.

Поскольку пользователи могут изменять информацию в строке запроса, поэтому необходимо все­гда проверять на допустимость данные в строке запроса.

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

Браузеры налагают ограничение на длину URL: ее предел — 2083 знака, но проблемы возникают и с более короткими URL, если пользователь отправляет их по электронной почте открытым текстом либо в мгновенном сообщении. По электронной почте разре­шена пересылка URL длиной до 70 символов (включая http:// или https*//)- В составе мгновенных сообщений разрешается отправлять URL длиной до 400 знаков.

Никогда не доверяйте значениям из строки запроса; они всегда должны про­веряться на допустимость.

Чтобы записать значения в строку запроса, добавьте в URL любую гиперссылку, доступную пользователю. Например, если есть элемент управления HyperLink со свойством NavigateUrl, установленным в «page.aspx», можно добавить строку «?user=tony» в HyperLink.NavigateUrl, чтобы URL приобрел вид «page.aspx?user=tony». Значения в строках запроса разделяют знаками «амперсанд» (&). Например, URL «page.aspx?user=tony&prefs=l&page=1252» посылает странице Page.aspx три значения в строке запроса: user со значением «tony», prefs со значением «1» и page со значением «1252».

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

Для чтения значения строки запроса необходимо обратиться к набору Request.QueryStrings, как к cookie. Продолжая предыдущий пример, включим в него код, позволяющий странице page.aspx обрабатывать строку запроса «user», вызывая Request.QueryStrings["user"] в С#. Напри­мер, следующий код показывает значения параметров user, prefs и page из строки запро­са в элементе управления Label1

//C#

Label1.Text = "User: " + Server.HtmlEncode(Request.QueryString["user"]) +

", Prefs: " + Server.HtmlEncode(Request.QueryString["prefs"]) +

", Page: " + Server.HtmlEncode(Request.QueryString["page"]);

Необходимо всегда кодировать cookie и значения в строке запроса с помощью Server.HtmlEncode перед отображением значения на HTML-страницах. Server.HtmlEncode заменяет HTML-код специальными символами, которые веб-браузер в состоянии толь­ко отображать, но не обрабатывать. Например, Server.Html Encode меняет знак «<» на «&lt». Просматривая значение в браузере, пользователь видит знак «<», но браузер не обработает ни HTML-код, ни клиентские сценарии.

Для обеспечения дополнительной защиты исполняющая среда, обнаружив в строке запроса HTML-код или сценарий, генерирует исключение System.Web.HttpRequestValidationException Следовательно, передавать HTML-код в строке запроса нельзя. Однако это ограничение администратор может отключить, так что не стоит полагаться на него в плане обеспечения безопасности.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]