HttpContext - это контекст одного запроса. Он предоставляет доступ к запросу, свойствам ответа и т. Д. 1058 * этого отдельного запроса. Вы не можете кэшировать его, он становится недействительным, как только этот запрос заканчивается.
Сессия - это еще одна временная вещь - она живет только один сеанс пользователя. Для каждого пользователя веб-приложения есть хотя бы один сеанс. Кэширование одного из этих сеансов в синглтоне гарантирует, что
- Ссылка станет недействительной через некоторое время, когда истечет время сеанса и
- Синглтон будет использовать только значения этого пользователя, игнорируя все еще. Это ошибка сама по себе, и отличный способ взломать приложение.
- Если администратор входит в систему, объект Session может применить настройки администратора ко всем в течение следующих 20, 30 или 60 минут.
Именно поэтому использование Session имеет смысл для промежуточное ПО для каждого запроса, а не службы Singleton.
Правильное использование HttpContext
Сеанс может быть достигнут только через контекст запроса, поэтому получение правильного сеанса означает получение исправить HttpContext. Правильный способ сделать это объяснен в ASP. NET Базового руководства Дэвида Фаулера :
❌ BAD. Этот пример сохраняет HttpContext в поле, а затем пытается использовать это позже.
private readonly HttpContext _context;
public MyType(IHttpContextAccessor accessor)
{
_context = accessor.HttpContext;
}
public void CheckAdmin()
{
if (!_context.User.IsInRole("admin"))
{
throw new UnauthorizedAccessException("The current user isn't an admin");
}
}
✅ ХОРОШО В этом примере сам IHttpContextAccesor хранится в поле и в нужное время использует поле HttpContext (проверка на ноль).
private readonly IHttpContextAccessor _accessor;
public MyType(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
public void CheckAdmin()
{
var context = _accessor.HttpContext;
if (context != null && !context.User.IsInRole("admin"))
{
throw new UnauthorizedAccessException("The current user isn't an admin");
}
}
Вместо этого используйте сервис Scoped
Поскольку Singleton не может знать, какой сеанс использовать. Один из вариантов - просто преобразовать этот сервис в сервис Scoped. В ASP. NET Core запрос определяет область действия. Вот как действия контроллера и промежуточное программное обеспечение конвейера получают доступ к правильному HttpContext для каждого запроса.
При условии, что служба используется действием или промежуточным программным обеспечением, возможно, единственное необходимое изменение - заменить AddSingleton<ThatService>
на AddScoped<ThatService>
Поворот таблиц или Инверсия управления
Другой вариант - для вызывающих абонентов этого синглтона должен предоставить сеанс для него. Вместо использования кэшированного сеанса, например:
public void SetStatus(string status)
{
_session.SetString(SessionKeys.UserStatus, "some value");
}
Запросите сеанс или HttpContext в качестве параметра:
public void SetStatus(string status,ISession session)
{
session.SetString(SessionKeys.UserStatus, "some value");
}
И пусть вызывающие абоненты передают ему правильный сеанс