Введение
В среде без сохранения состояния, такой как веб-приложение, понимание концепции состояния сеанса не имеет реального смысла. Тем не менее, эффективное управление состоянием является обязательной функцией для большинства веб-приложений. Microsoft ASP.NET, как и многие другие среды серверного программирования, предоставляют уровень абстракции, который позволяет приложениям хранить постоянные данные отдельно для каждого пользователя и для каждого приложения.
Важно отметить, что состояние сеанса веб-приложения — это данные, которые приложение кэширует и извлекает по различным запросам. Сеанс представляет собой все запросы, отправленные пользователем при подключении к сайту, а состояние сеанса — это набор постоянных данных, создаваемых и потребляемых пользователем во время сеанса. Состояние каждого сеанса независимо друг от друга и перестает существовать после завершения сеанса пользователя.
Состояние сеанса не имеет соответствия ни с одним из логических объектов, составляющих протокол и спецификацию HTTP. Сессии — это уровень абстракции, созданный серверными средами разработки, такими как традиционные ASP и ASP.NET. То, как ASP.NET отображает состояние сеанса и как состояние сеанса реализуется внутри, зависит от инфраструктуры платформы. Таким образом, традиционные ASP и ASP.NET реализуют состояние сеанса совершенно по-разному, и в следующей версии ASP.NET ожидаются дальнейшие улучшения и усовершенствования.
В этой статье обсуждается, как реализовать состояние сеанса в ASP.NET 1.1 и как оптимизировать управление состоянием сеанса в управляемых веб-приложениях.
Обзор состояния сеанса ASP.NET
Состояние сеанса не является частью инфраструктуры HTTP. То есть должен быть структурный компонент, который связывает состояние сеанса с каждым входящим запросом. Среда выполнения (традиционный ASP или ASP.NET) может принимать ключевые слова, такие как Session, и использовать их для обозначения блока данных, хранящихся на сервере. Чтобы успешно разрешить вызовы объекта сеанса, среда выполнения должна добавить состояние сеанса в контекст вызова обрабатываемого запроса. То, как это делается, варьируется в зависимости от платформы, но это имеет фундаментальное значение для веб-приложений с отслеживанием состояния.
В традиционном ASP состояние сеанса реализуется в виде свободнопоточных COM-объектов, содержащихся в библиотеке asp.dll. (Вам интересно? На самом деле CLSID этого объекта — D97A6DA0-A865-11cf-83AF-00A0C90C2BD8.) Этот объект хранит данные, организованные в виде коллекции пар имя/значение. Заполнитель «имя» представляет ключ, используемый для получения информации, а заполнитель «значение» представляет то, что хранится в состоянии сеанса. Пары имя/значение группируются по идентификатору сеанса, так что каждый пользователь видит только те пары имя/значение, которые он создал.
В ASP.NET интерфейс программирования состояния сеанса почти такой же, как и в традиционном ASP. Но их базовые реализации совершенно разные. Первый более гибок, масштабируем и имеет более сильные возможности программирования, чем второй. Прежде чем мы углубимся в состояние сеанса ASP.NET, давайте кратко рассмотрим некоторые структурные возможности инфраструктуры сеансов ASP.NET.
В ASP.NET любой входящий HTTP-запрос передается через HTTP-модуль. Каждый модуль может фильтровать и изменять большой объем информации, передаваемой по запросу. Информация, связанная с каждым запросом, называется «контекстом вызова», который в программировании представлен объектом HttpContext. Мы не должны думать о контексте запроса как о еще одном контейнере информации о состоянии, хотя предоставляемая им коллекция Items — это всего лишь контейнер данных. Объект HttpContext отличается от всех других объектов состояния (например, сеанса, приложения и кэша) тем, что он имеет ограниченный срок жизни, превышающий время, необходимое для обработки запроса. Когда запрос проходит через ряд зарегистрированных HTTP-модулей, его объект HttpContext будет содержать ссылку на объект состояния. Когда запрос наконец может быть обработан, связанный контекст вызова привязывается к конкретному сеансу (сеансу) и глобальным объектам состояния (приложению и кэшу).
HTTP-модуль, ответственный за настройку состояния сеанса каждого пользователя, — SessionStateModule. Структура этого модуля разработана на основе интерфейса IHttpModule, который предоставляет большое количество служб, связанных с состоянием сеанса, для приложений ASP.NET. Включает создание идентификаторов сеансов, управление сеансами без файлов cookie, получение данных сеанса от внешних поставщиков состояний и привязку данных к контексту вызова запроса.
Модуль HTTP не хранит данные сеанса внутри себя. Состояние сеанса всегда сохраняется во внешнем компоненте, называемом «поставщиком состояния». Поставщик состояний полностью инкапсулирует данные о состоянии сеанса и взаимодействует с другими частями через методы интерфейса IStateClientManager. HTTP-модуль состояния сеанса вызывает методы этого интерфейса для чтения и сохранения состояния сеанса. ASP.NET 1.1 поддерживает три разных поставщика состояний, как показано в таблице 1.
Таблица 1. Статус поставщика клиента
Описание поставщика
Значения сеанса InProc остаются активными объектами в памяти рабочего процесса ASP.NET (aspnet_wp.exe или w3wp.exe в Microsoft® Windows Server® 2003). Это опция по умолчанию.
Значения сеанса StateServer сериализуются и сохраняются в памяти в отдельном процессе (aspnet_state.exe). Этот процесс также может запускаться на других компьютерах.
Значения сеанса SQLServer сериализуются и сохраняются в таблицах Microsoft® SQL Server®. Экземпляры SQL Server могут работать локально или удаленно.
HTTP-модуль состояния сеанса считывает текущий выбранный поставщик состояния из раздела <sessionState> файла web.config.
<sessionState mode="InProc | StateServer | SQLServer />;
В зависимости от значения атрибута mode состояние сеанса будет извлекаться и сохраняться в разных процессах посредством различных шагов. По умолчанию состояние сеанса сохраняется в локальном Рабочий процесс ASP.NET. В особых случаях он хранится в выделенном слоте объекта ASP.NET Cache (недоступно программно). Состояние сеанса также может храниться снаружи, даже в удаленном процессе (например, в Windows). NT с именем aspnet_state.exe). Третий вариант — сохранить состояние сеанса в специальной таблице базы данных, управляемой SQL Server 2000.
Модуль HTTP десериализует значение сеанса в начале запроса, превращая его в словари. (на самом деле объекты типа HttpSessionState) затем доступны программно через свойство Session, предоставляемое классами (например, HttpContext и Page). Привязка длится до тех пор, пока запрос не завершится успешно, все значения статуса сериализуются обратно. для поставщика статуса и доступен для других запросов.
На рисунке 1 показана связь между запрошенной страницей ASP.NET и значениями сеанса. Код, используемый каждой страницей, связан с атрибутом Session в классе страницы. то же, что и у традиционного ASP.
Рис. 1. Архитектура состояния сеанса в ASP.NET 1.1.
Физическое значение состояния сеанса блокируется на время, необходимое для выполнения запроса. Эта блокировка управляется изнутри модулем HTTP и используется для синхронизации доступа к состоянию сеанса.
Модуль состояния сеанса создает экземпляр поставщика состояния приложения и инициализирует его с помощью информации, считанной из файла web.config. Далее каждый провайдер продолжит свои операции инициализации. В зависимости от типа провайдера его операции инициализации будут сильно различаться. Например, диспетчер состояний SQL Server откроет соединение с заданной базой данных, а диспетчер вне процесса проверит указанный TCP-порт. С другой стороны, менеджер состояний InProc сохранит ссылку на функцию обратного вызова. Это действие выполняется, когда элемент удаляется из кэша, и используется для запуска события Session_OnEnd приложения.
Синхронный доступ к состоянию сеанса
Что происходит, когда веб-страница выполняет очень простой и интуитивно понятный вызов свойства Session? Многие операции выполняются в фоновом режиме, как показано в следующем громоздком коде:
int siteCount = Convert.ToInt32(Session["Counter"]);
Приведенный выше код фактически обращается к значению сеанса, созданному модулем HTTP в локальной памяти. считывает данные от конкретного поставщика состояний (см. рисунок 1). Что произойдет, если другие страницы также попытаются синхронно получить доступ к состоянию сеанса? В этом случае текущий запрос может прекратить обработку противоречивых или устаревших данных. Чтобы избежать этого, модуль состояния сеанса реализует механизм блокировки чтения/записи и очередь доступа к значениям состояния. Страницы с разрешениями на запись в состоянии сеанса сохранят блокировку записи для этого сеанса до тех пор, пока запрос не завершится.
Страница может запросить разрешение на запись состояния сеанса, установив для свойства EnableSessionState директивы @Page значение true. (Это настройка по умолчанию). Однако страница также может иметь доступ только для чтения к состоянию сеанса, например, если для свойства EnableSessionState установлено значение ReadOnly. В этом случае модуль сохранит блокировку чтения для этого сеанса до тех пор, пока запрос этой страницы не завершится. В результате произойдет одновременное чтение.
Если запрос страницы устанавливает блокировку чтения, другие одновременные запросы в том же сеансе не смогут обновлять состояние сеанса, но, по крайней мере, смогут читать. То есть, если в данный момент для сеанса обрабатывается запрос только для чтения, ожидающий запрос только для чтения будет иметь более высокий приоритет, чем запрос, требующий полного доступа. Если запрос страницы устанавливает блокировку записи для состояния сеанса, все остальные страницы будут заблокированы независимо от того, хотят ли они читать или записывать контент. Например, если два кадра пытаются записать в сеанс одновременно, один кадр должен дождаться завершения другого, прежде чем он сможет записать.
Сравнение поставщиков состояний
По умолчанию приложения ASP.NET хранят состояние сеанса в памяти рабочего процесса, а именно в выделенном слоте объекта Cache. Если выбран режим InProc, состояние сеанса сохраняется в слотах объекта Cache. Этот слот помечен как частный слот, и к нему нельзя получить программный доступ. Другими словами, если вы перечислите все элементы в кэше данных ASP.NET, никакие объекты, похожие на данное состояние сеанса, не будут возвращены. Объекты кэша предоставляют два типа слотов: частные и общедоступные. Программисты могут добавлять и обрабатывать общедоступные слоты, но частные слоты могут использоваться только системой (в частности, классами, определенными в части system.web).
Состояние каждого активного сеанса занимает выделенный слот в кэше. Слот получает имя на основе идентификатора сеанса, а его значением является экземпляр внутреннего необъявленного класса с именем SessionStateItem. Поставщик состояний InProc получает идентификатор сеанса и извлекает соответствующий элемент из кэша. Содержимое объекта SessionStateItem затем вводится в объект словаря HttpSessionState, и приложение получает к нему доступ через свойство Session. Обратите внимание, что в ASP.NET 1.0 есть ошибка, из-за которой частные слоты объекта Cache программно перечисляются. Если вы запустите следующий код в ASP.NET 1.0, вы сможете перечислить элементы, соответствующие объектам, содержащимся в каждом текущем активном состоянии сеанса.
foreach (элемент DictionaryEntry в кеше)
{
Response.Write(elem.Key + ": " + elem.Value.ToString());
}
Эта ошибка устранена в ASP.NET 1.1, и при перечислении кэшированного содержимого системные слоты больше не отображаются.
InProc, вероятно, является самым быстрым вариантом доступа на сегодняшний день. Но имейте в виду, что чем больше данных хранится в сеансе, тем больше памяти потребляет веб-сервер, что потенциально увеличивает риск снижения производительности. Если вы планируете использовать какое-либо внепроцессное решение, вам следует тщательно рассмотреть возможные последствия сериализации и десериализации. Внепроцессное решение использует службу Windows NT (aspnet_state.exe) или таблицу SQL Server для хранения значений сеанса. Таким образом, состояние сеанса остается вне рабочего процесса ASP.NET, и для сериализации и десериализации между состоянием сеанса и реальным носителем данных требуются дополнительные уровни кода. Это происходит всякий раз, когда запрос обрабатывается, и затем его необходимо максимально оптимизировать.
Поскольку данные сеанса необходимо скопировать из внешнего репозитория в локальный словарь сеансов, запрос приводит к снижению производительности от 15 % (внепроцессный) до 25 % (SQL Server). Обратите внимание: хотя это лишь приблизительная оценка, она должна быть близка к минимальному воздействию, а максимальное воздействие будет намного выше этого значения. Фактически эта оценка не полностью учитывает сложность типов, фактически сохраняемых в состоянии сеанса.
В сценарии внепроцессного хранения состояние сеанса сохраняется дольше, что делает приложение более мощным, поскольку оно защищает от сбоев Microsoft® Internet Information Services (IIS) и ASP.NET. Отделив состояние сеанса от приложений, вы также можете легче расширить существующие приложения до архитектур веб-фермы и веб-сада. Кроме того, состояние сеанса сохраняется во внешнем процессе, что существенно исключает риск периодической потери данных из-за циклов процесса.
Вот как использовать службы Windows NT. Как упоминалось выше, служба NT — это процесс с именем aspnet_state.exe, обычно расположенный в папке C:WINNTMicrosoft.NETFrameworkv1.1.4322.
Фактический каталог зависит от версии Microsoft® .NET Framework, которую вы фактически используете. Перед использованием сервера состояний необходимо убедиться, что служба готова и работает на локальном или удаленном компьютере, который используется в качестве устройства хранения сеансов. Служба состояний является частью ASP.NET и устанавливается вместе с ней, поэтому вам не нужно запускать дополнительный установщик. По умолчанию служба состояния не запущена, и ее необходимо запускать вручную. Приложение ASP.NET попытается установить соединение с сервером состояний сразу после загрузки. Следовательно, служба должна быть готова и запущена, иначе будет выдано исключение HTTP. На следующем изображении показано диалоговое окно свойств службы.
Рис. 2. Диалоговое окно «Свойства сервера состояний ASP.NET».
Приложениям ASP.NET необходимо указать TCP/IP-адрес компьютера, на котором расположена служба состояния сеанса. Следующие настройки необходимо ввести в файл web.config приложения.
<конфигурация>;
<система.веб>;
<sessionState
режим = «Статесервер»
stateConnectionString="tcpip=expoware:42424" />;
</system.web>;
</configuration>;
Атрибут stateConnectionString содержит IP-адрес компьютера и порт, используемый для обмена данными. Адрес компьютера по умолчанию — 127.0.0.1 (localhost), а порт по умолчанию — 42424. Вы также можете указать компьютер по имени. Использование локального или удаленного компьютера полностью прозрачно для кода. Обратите внимание, что в имени нельзя использовать символы, отличные от ASCII, а номер порта является обязательным.
Если вы используете внепроцессное хранилище сеансов, состояние сеанса по-прежнему будет существовать и доступно для использования в будущем независимо от того, что произойдет с рабочим процессом ASP.NET. Если услуга будет прервана, данные будут сохранены и автоматически восстановлены при восстановлении услуги. Однако если служба поставщика статуса остановится или выйдет из строя, данные будут потеряны. Если вы хотите, чтобы ваше приложение было мощным, используйте режим SQLServer вместо режима StateServer.
<конфигурация>;
<система.веб>;
<sessionState
режим="SQLServer"
sqlConnectionString="server=127.0.0.1;uid=<идентификатор пользователя>;;pwd=<пароль>;;" />;
</system.web>;
</configuration>;
Вы можете указать строку подключения через атрибут sqlConnectionString. Обратите внимание, что строка атрибута должна содержать идентификатор пользователя, пароль и имя сервера. Он не может содержать такие теги, как «База данных» и «Исходный каталог», поскольку по умолчанию эта информация имеет фиксированное имя. Идентификаторы пользователей и пароли можно заменить встроенными настройками безопасности.
Как создать базу данных? ASP.NET предоставляет две пары сценариев для настройки среды базы данных. Первая пара сценариев называется InstallSqlState.sql и UninstallSqlState.sql и расположена в той же папке, что и служба состояния сеанса NT. Они создают базу данных с именем ASPState и несколько хранимых процедур. Однако данные хранятся во временной базе данных TempDB SQL Server. Это означает, что если компьютер SQL Server будет перезагружен, данные сеанса будут потеряны.
Чтобы обойти это ограничение, используйте вторую пару скриптов. Вторая пара скриптов называется InstallPersistSqlState.sql и UninstallPersistSqlState.sql. В этом случае создается база данных ASPState, но таблицы создаются в той же базе данных и также являются постоянными. При установке поддержки сеансов SQL Server также создается задание для удаления истекших сеансов в базе данных состояний сеансов. Задание называется ASPState_Job_DeleteExpiredSessions и всегда выполняется. Обратите внимание: для правильной работы этого задания должна быть запущена служба SQLServerAgent.
Независимо от того, какой режим вы выберете, способ кодирования операций состояния сеанса не изменится. Вы всегда можете работать со свойством Session и читать и записывать значения как обычно. Все различия в поведении обрабатываются на более низком уровне абстракции. Сериализация состояний, пожалуй, самое важное различие между режимами сеанса.
Сериализация и десериализация состояния.
При использовании внутрипроцессного режима объекты сохраняются в состоянии сеанса как активные экземпляры соответствующих классов. Если реальной сериализации и десериализации не происходит, это означает, что вы действительно можете хранить в сеансе любой созданный вами объект (включая объекты, которые не могут быть сериализованы, и COM-объекты), и доступ к ним не будет слишком дорогим. Если вы выберете поставщика состояния вне процесса, это совсем другая история.
Во внепроцессной архитектуре значения сеанса копируются с локального носителя (внешняя база данных AppDomain) в память AppDomain, который обрабатывает запрос. Для выполнения этой задачи необходим уровень сериализации/десериализации, который представляет собой одну из основных затрат поставщиков состояний вне процесса. Основное влияние, которое эта ситуация оказывает на ваш код, заключается в том, что в словаре сеанса можно хранить только сериализуемые объекты.
ASP.NET использует два метода сериализации и десериализации данных в зависимости от типа используемых данных. Для базовых типов ASP.NET использует оптимизированный внутренний сериализатор; для других типов, включая объекты и определяемые пользователем классы, ASP.NET использует двоичный форматировщик .NET. Базовые типы включают строки, даты и время, логические значения, байты, символы и все числовые типы. Для этих типов использование специального сериализатора выполняется быстрее, чем использование стандартного стандартного средства форматирования двоичных файлов .NET.
Оптимизированный сериализатор не публикуется и не документируется. Это всего лишь двоичное устройство чтения/записи, использующее простую, но эффективную архитектуру хранения. Сериализатор использует класс BinaryWriter для записи байтового представления типа, а затем записывает байтовое представление значения, соответствующего этому типу. При чтении сериализованных байтов класс сначала извлекает байт, определяет тип данных для чтения, а затем вызывает метод ReadXxx для конкретного типа в классе BinaryReader.
Обратите внимание, что размер логических и числовых типов хорошо известен, но не строк. В базовом потоке данных строка всегда имеет префикс фиксированной длины (7-битный целочисленный код, записываемый одновременно), и считыватель использует этот факт для определения правильного размера строки. Значение даты сохраняется путем записи только общего количества токенов, составляющих дату. Поэтому для сериализации сеанса дата должна иметь тип Int64.
Вы можете использовать класс BinaryFormatter для выполнения операций сериализации над более сложными объектами (а также пользовательскими объектами), если содержащий их класс помечен как сериализуемый. Все небазовые типы идентифицируются одним и тем же идентификатором типа и хранятся в том же потоке данных, что и базовые типы. В целом операции сериализации могут привести к снижению производительности на 15–25%. Однако обратите внимание, что это приблизительная оценка, основанная на предположении, что используются базовые типы. Чем сложнее используемые типы, тем больше накладные расходы.
Эффективное хранение данных сеанса сложно реализовать без широкого использования примитивных типов. Таким образом, по крайней мере теоретически, использование трех слотов сеанса для сохранения трех разных строковых свойств объекта лучше, чем сериализация всего объекта. Но что, если объект, который вы хотите сериализовать, содержит 100 свойств? Хотите ли вы использовать 100 слотов или только один слот? Во многих случаях лучшим подходом является преобразование сложного типа в несколько более простых типов. Этот подход основан на преобразователях типов. «Преобразователь типов» — это облегченный сериализатор, который возвращает ключевые свойства типа в виде набора строк. Преобразователи типов — это внешние классы, которые привязаны к базовому классу с помощью атрибутов. Типограф должен решить, какие свойства сохранять и как. Преобразователи типов также полезны для хранения ViewState и представляют собой более эффективный метод хранения сеансов, чем средства двоичного форматирования.
Жизненный цикл сеанса
Важным моментом в управлении сеансами ASP.NET является то, что жизненный цикл объекта состояния сеанса начинается только тогда, когда первый элемент добавляется в словарь в памяти. Сеанс ASP.NET считается запущенным только после выполнения следующего фрагмента кода.
Session["MySlot"] = "Некоторые данные";
Словарь сеанса обычно содержит тип объекта. Для обратного чтения возвращаемое значение необходимо преобразовать в более конкретный тип.
string data = (string) Session["MySlot"];
Когда страница сохраняет данные в сеансе, значение будет загружено в специально созданный класс словаря, содержащийся в классе HttpSessionState. Содержимое словаря загружается в поставщик состояний после завершения текущего обрабатываемого запроса. Если состояние сеанса пусто, поскольку данные не были помещены в словарь программным путем, данные не будут сериализованы на носитель данных и, что более важно, не будут обслуживаться в кэше ASP.NET, SQL Server или службах состояний NT. слот для отслеживания текущего сеанса. Это сделано из соображений производительности, но оказывает важное влияние на то, как обрабатываются идентификаторы сеансов: новый идентификатор сеанса будет генерироваться для каждого запроса до тех пор, пока некоторые данные не будут сохранены в словаре сеансов.
Когда необходимо связать состояние сеанса с обрабатываемым запросом, HTTP-модуль получает идентификатор сеанса (если это не инициирующий запрос) и ищет его в настроенном поставщике состояний. Если данные не возвращаются, модуль HTTP генерирует новый идентификатор сеанса для запроса. Это можно легко проверить на следующей странице:
<%@ Page Language="C#" Trace="true" %>;
</html>;
<тело>;
<form runat="сервер">;
<asp:button runat="server" text="Click" />;
</форма>;
</тело>;
</html>;
Каждый раз, когда вы нажимаете кнопку и возвращаетесь на страницу, создается новый идентификатор сеанса и записывается информация отслеживания.
Рисунок 3. В приложении, которое не хранит данные в словаре сеанса, для каждого запроса генерируется новый идентификатор сеанса.
А как насчет события Session_OnStart? Будет ли событие вызываться для каждого запроса? Если ваше приложение определяет обработчик Session_OnStart, состояние сеанса всегда сохраняется, даже если оно пустое. Таким образом, идентификатор сеанса всегда постоянен для всех запросов после первого запроса. Используйте обработчик Session_OnStart только в случае крайней необходимости.
Если время сеанса истекло или он был прерван, его идентификатор сеанса не изменится при следующем обращении к приложению без отслеживания состояния. Он спроектирован таким образом, что идентификатор сеанса сохраняется до конца сеанса браузера, даже если срок действия состояния сеанса истекает. То есть один и тот же идентификатор сеанса всегда используется для представления нескольких сеансов, если экземпляр браузера один и тот же.
Событие Session_OnEnd отмечает конец сеанса и используется для выполнения любого кода очистки, необходимого для завершения сеанса. Однако обратите внимание, что это событие поддерживается только в режиме InProc, то есть только тогда, когда данные сеанса хранятся в рабочем процессе ASP.NET. Чтобы событие Session_OnEnd было вызвано, сначала должно существовать состояние сеанса, а это означает, что некоторые данные должны быть сохранены в состоянии сеанса, и должен быть выполнен хотя бы один запрос.
В режиме InProc состояние сеанса, добавленное в кэш как элементы, имеет переменную политику срока действия. Переменный срок действия означает, что если элемент не используется в течение определенного периода времени, он будет удален. Срок действия любых запросов, обработанных в течение этого периода, будет сброшен. Интервал элемента состояния сеанса равен тайм-ауту сеанса. Техника, используемая для сброса времени истечения состояния сеанса, очень проста и интуитивно понятна: модуль HTTP сеанса просто считывает элементы состояния сеанса, хранящиеся в кэше ASP.NET. Если внутренняя структура объекта ASP.NET Cache известна, модуль выполнит вычисления для сброса срока действия переменной. Поэтому, когда срок действия кэшированного элемента истекает, время сеанса истекает.
Просроченные элементы будут автоматически удалены из кэша. Модуль сеанса состояния также представляет функцию обратного вызова удаления как часть политики срока действия для этого проекта. Кэш автоматически вызовет функцию удаления, которая затем вызовет событие Session_OnEnd. Если приложение выполняет управление сеансом через внепроцессный компонент, конечное событие никогда не будет вызвано.
Сеансы без файлов cookie.
Каждый активный сеанс ASP.NET идентифицируется с помощью 120-битной строки, состоящей только из символов, разрешенных URL-адресом. Идентификатор сеанса генерируется с использованием криптографического поставщика генератора случайных чисел (ГСЧ). Поставщик услуг возвращает последовательность из 15 случайно сгенерированных чисел (15 байт x 8 бит = 120 бит). Затем массив случайных чисел сопоставляется с допустимыми символами URL-адреса и возвращается в виде строки.
Строка идентификатора сеанса отправляется в браузер и возвращается серверному приложению одним из двух способов: с использованием файла cookie (как в традиционном ASP) или измененного URL-адреса. По умолчанию модуль состояния сеанса создает файл cookie HTTP на стороне клиента, но можно использовать измененный URL-адрес, встраивающий строку идентификатора сеанса (особенно для браузеров, которые не поддерживают файлы cookie). Какой метод используется, зависит от настроек конфигурации, хранящихся в файле web.config приложения. Для настройки параметров сеанса вы можете использовать раздел <sessionState> и атрибут Cookieless.
<sessionState cookieless="true|false" />
По умолчанию атрибут Cookieless имеет значение false, что указывает на использование файлов cookie. Фактически, файл cookie — это просто текстовый файл, размещаемый на жестком диске клиента веб-страницей. В ASP.NET файл cookie представлен экземпляром класса HttpCookie. Обычно файл cookie содержит имя, набор значений и срок действия. Если для атрибута Cookieless установлено значение false, модуль состояния сеанса фактически создаст файл cookie с именем ASP.NET_SessionId и сохранит в нем идентификатор сеанса. Следующий псевдокод демонстрирует процесс создания файла cookie:
HttpCookie sessionCookie;
sessionCookie = новый HttpCookie("ASP.NET_SessionId", sessionID);
sessionCookie.Path = "/";
Срок действия сеансового файла cookie очень короткий, и срок действия обновляется после успешного выполнения каждого запроса. Атрибут Expires файла cookie указывает время истечения срока действия файла cookie на клиенте. Если файл cookie сеанса не задан явно, свойство Expires по умолчанию имеет значение DateTime.MinValue, что является наименьшей единицей времени, разрешенной .NET Framework.
Чтобы отключить файлы cookie сеанса, установите для атрибута Cookieless значение true в файле конфигурации следующим образом:
<configuration>;
<система.веб>;
<sessionState Cookieless="true" />;
</system.web>;
</configuration>;
Предположим, что вы запрашиваете страницу по следующему URL-адресу:
http://www.contoso.com/sample.aspx.
Фактическое содержимое, отображаемое в адресной строке браузера, будет другим и теперь содержит идентификатор сеанса. , как показано ниже. Показано в:
http://www.contoso.com/(5ylg0455mrvws1uz5mmaau45)/sample.aspx
При создании экземпляра HTTP-модуля состояния сеанса модуль проверяет значение атрибута Cookieless. Если это правда, перенаправляет запрос (HTTP 302) на измененный виртуальный URL-адрес, содержащий идентификатор сеанса, предшествующий имени страницы. Когда запрос будет обработан снова, идентификатор сеанса будет включен в запрос. Если делается запрос на запуск нового сеанса, модуль HTTP генерирует новый идентификатор сеанса, а затем перенаправляет запрос. Если запрос отправляется обратно, идентификатор сеанса уже существует, поскольку при обратной передаче используются относительные URL-адреса.
Недостаток использования сеансов без файлов cookie заключается в том, что состояние сеанса теряется при вызове абсолютного URL-адреса. При использовании файлов cookie вы можете очистить адресную строку, перейти в другое приложение, а затем вернуться к предыдущему приложению и получить то же значение сеанса. Если вы сделаете это, когда файлы cookie сеанса отключены, данные сеанса будут потеряны. Например, следующий код прервет сеанс:
<a runat="server" href="/code/page.aspx">;Click</a>.
Если вам нужно использовать абсолютный URL-адрес, воспользуйтесь некоторыми приемами, чтобы вручную измените идентификатор сеанса, добавленный в URL-адрес. Вы можете вызвать метод ApplyAppPathModifier в классе HttpResponse.
<a runat="сервер"
href=<% =Response.ApplyAppPathModifier("/code/page.aspx")%>; >;Click</a>;
Метод ApplyAppPathModifier будет использовать строку, представляющую URL-адрес, и вернет абсолютный URL-адрес, встраивающий информацию о сеансе. Этот метод особенно полезен, например, когда вам нужно перенаправить со страницы HTTP на страницу HTTPS.
Сводное
состояние сеанса изначально было представлено в традиционном ASP как API на основе словаря, который позволял разработчикам хранить пользовательские данные во время сеанса. В ASP.NET состояние сеанса поддерживает две основные функции: хранение и передачу идентификатора сеанса без файлов cookie, а также поставщиков состояний, где фактически хранятся данные сеанса. Для реализации этих двух новых возможностей ASP.NET использует модуль HTTP для управления привязкой между состоянием сеанса и контекстом обрабатываемого запроса.
В традиционном ASP использование состояния сеанса означает использование файлов cookie. В ASP.NET это уже не так, поскольку можно использовать архитектуру без файлов cookie. Благодаря возможностям модуля HTTP запрошенный URL-адрес можно разложить так, чтобы он содержал идентификатор сеанса, а затем перенаправить. Затем модуль HTTP извлекает идентификатор сеанса из URL-адреса и использует его для получения любого сохраненного состояния.
Физическое состояние сеанса может храниться в трех местах: внутрипроцессной памяти, внепроцессной памяти и таблицах SQL Server. Данные должны быть сериализованы/десериализованы, прежде чем они смогут быть использованы приложением. Модуль HTTP копирует значение сеанса от провайдера в память приложения в начале запроса. После завершения запроса измененный статус возвращается провайдеру. Эта передача данных будет иметь различные степени неблагоприятного воздействия на производительность, но значительно повысит надежность и стабильность и облегчит поддержку архитектурам веб -фермы и веб -сада.