Сессии

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 03.11.2019

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

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

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

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

Чтобы использовать сессии, необходимо сконфигурировать их параметры в классе Startup. Все сессии работают поверх объекта IDistributedCache, и ASP.NET Core предоставляет встроенную реализацию IDistributedCache, которую мы можем использовать. И для этого изменим класс Startup следующим образом:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Linq;

namespace HelloApp
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDistributedMemoryCache();
            services.AddSession();
        }
        public void Configure(IApplicationBuilder app)
        {
            app.UseSession();
            app.Run(async (context) =>
            {
                if (context.Session.Keys.Contains("name"))
                    await context.Response.WriteAsync($"Hello {context.Session.GetString("name")}!");
                else
                {
                    context.Session.SetString("name", "Tom");
                    await context.Response.WriteAsync("Hello World!");
                }
            });
        }
    }
}

В методе ConfigureServices() добавляются необходимые сервисы:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDistributedMemoryCache();
    services.AddSession();
}

В методе Configure() механизм работы с сессиями встраивается в конвейер обработки запроса:

public void Configure(IApplicationBuilder app)
{
    app.UseSession();	// добавляем механизм работы с сессиями
    app.Run(async (context) =>
    {
        if(context.Session.Keys.Contains("name"))
            await context.Response.WriteAsync($"Hello {context.Session.GetString("name")}!");
        else
        {
            context.Session.SetString("name", "Tom");
            await context.Response.WriteAsync("Hello World!");
        }
    });
}

Если мы вдруг не используем app.UseSession() или попробуем обратиться к сессии до применения этого метода, то получим исключение InvalidOperationException.

После вызова app.UseSession() мы сможем использовать сессии у объекта HttpContext. В данном случае мы проверяем, определен ли в сессии ключ "name". Если ключ определен, то передаем ответ значение по этому ключу. Если ключ не определен, устанавливаем его.

Сессии в ASP.NET Core

После первого запроса мы сможем через инстументы браузера для разработчиков найти куку .AspNetCore.Session, которая будет представлять идентификатор сессии:

Управление сессиями в ASP.NET Core

Управление сессией

Объект Session определяет ряд свойств и методов, которые мы можем использовать:

  • Keys: свойство, представляющее список строк, который хранит все доступные ключи

  • Clear(): очищает сессию

  • Get(string key): получает по ключу key значение, которое представляет массив байтов

  • GetInt32(string key): получает по ключу key значение, которое представляет целочисленное значение

  • GetString(string key): получает по ключу key значение, которое представляет строку

  • Set(string key, byte[] value): устанавливает по ключу key значение, которое представляет массив байтов

  • SetInt32(string key, int value): устанавливает по ключу key значение, которое представляет целочисленное значение value

  • SetString(string key, string value): устанавливает по ключу key значение, которое представляет строку value

  • Remove(string key): удаляет значение по ключу

Настройка сессии

Для разграничения сессий для них устанавливается идентификатор. Каждая сессия имеет свой идентификатор, который сохрнаяется в куках. По умолчанию эти куки имеют название ".AspNet.Session". И также по умолчанию куки имеют настройку CookieHttpOnly=true, поэтому они не доступны для клиентских скриптов из браузера. Но мы можем переопределить ряд настроек сессии с помощью свойств объекта SessionOptions:

  • Cookie.Name: имя куки

  • Cookie.Domain: домен, для которого устаналиваются куки

  • Cookie.HttpOnly: доступны ли куки только при передаче через HTTP-запрос

  • Cookie.Path: путь, который используется куками

  • Cookie.Expiration: время действия куки в виде объекта System.TimeSpan

  • Cookie.IsEssential: при значении true указывает, что куки критичны и необходимы для работы этого приложения

  • IdleTimeout: время действия сессии в виде объекта System.TimeSpan прм неактивности пользователя. При каждом новом запросе таймаут сбрасывается. Этот параметр не зависит от Cookie.Expiration.

Для использования этих свойств изменим код метода ConfigureServices():

public void ConfigureServices(IServiceCollection services)
{
    services.AddDistributedMemoryCache();
    services.AddSession(options =>
    {
        options.Cookie.Name = ".MyApp.Session";
        options.IdleTimeout = TimeSpan.FromSeconds(3600);
		options.Cookie.IsEssential = true;
    });
}

Хранение сложных объектов

В случае выше в сессиях хранились простые строки. Если же надо сохранить какой-то сложный объект, то его надо сериализовать в строку, а при получении из сессии - обратно десериализовать. Как правило, для этого определяются методы расширения для объекта ISession, а для сериализации используется Json.NET. В частности, добавим следующий класс:

using Microsoft.AspNetCore.Http;
using System.Text.Json;

namespace HelloApp
{
    public static class SessionExtensions
    {
        public static void Set<T>(this ISession session, string key, T value)
        {
            session.SetString(key, JsonSerializer.Serialize<T>(value));
        }

        public static T Get<T>(this ISession session, string key)
        {
            var value = session.GetString(key);
            return value == null ? default(T) : JsonSerializer.Deserialize<T>(value);
        }
    }
}

Метод Set сохраняет в сессию данные, а метод Get извлекает их из сессии.

Допустим, у нас есть класс Person:

class Person
{
	public string Name { get; set; }
	public int Age { get; set; }
}

Сохраним в сессию и обратно десериализуем объект в методе Configure:

public class Startup
{
	public void ConfigureServices(IServiceCollection services)
	{
		services.AddDistributedMemoryCache();
		services.AddSession();
	}

	public void Configure(IApplicationBuilder app)
	{
		app.UseSession();
		app.Run(async (context) =>
		{
			if (context.Session.Keys.Contains("person"))
			{
				Person person = context.Session.Get<Person>("person");
				await context.Response.WriteAsync($"Hello {person.Name}, your age: {person.Age}!");
			}
			else
			{
				Person person = new Person { Name = "Tom", Age = 22 };
				context.Session.Set<Person>("person", person);
				await context.Response.WriteAsync("Hello World!");
			}
		});
	}
}
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850