Почему Session.Clear() - не работает?
Я использую .NET Core 2.1
и пытается использовать сессию как часть аутентификации. Я ожидаю, что это произойдет:
- Человек входит в
- Я устанавливаю значение сеанса
- Сессионный cookie возвращается
- Человек нажмите выйти
- Я очищаю сессию
HttpContext.Session.Clear()
Затем я пытаюсь имитировать ситуацию, когда cookie-файл Session был украден у исходного пользователя, поэтому я создаю еще один запрос к серверу и ожидаю, что значение, установленное в сеансе, не будет. Похоже, он все еще держит его даже после вызова Session.Clear()
,
Код:
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(10);
options.Cookie.Name = SessionCookieName;
options.Cookie.HttpOnly = true;
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSession();
}
Действие входа в систему:
HttpContext.Session.SetInt32(SessionConstants.Key, value);
Действие выхода из системы:
HttpContext.Session.Clear();
Действие CheckLoginStatus:
var sessionValue = HttpContext.Session.GetInt32(SessionConstants.Key);
Тест, который наслаждается проблемой:
var httpClientGenuineRequest = GetClient();
var httpClientAttacker = GetClient();
//Given
var request = new LoginRequest()
{
//filled properties
};
var loginResponse = await httpClientGenuineMember.PostAsync("urlToLoginAction", new JsonContent(request));
AddResponseCookiesToHeaders(httpClientAttacker, loginResponse);
await httpClientGenuineMember.PostAsync("urlToLogoutAction", new JsonContent(request));
//When
var response = await httpClientAttacker.GetAsync("urlToCheckStatusAction");
//Here the actual result is true
var actualResult = response.GetResult<bool>();
//Then
var expectedResult = false;
Приведенный выше пример не полный. Вопрос касается только значений Session, поэтому я избавился от всего другого кода аутентификации, чтобы сделать его более понятным.
Для меня это выглядит так, HttpContext.Session.Clear
не очищает сеанс или значение сохраняется в файле cookie сеанса (что не имеет никакого смысла)?
Также, когда я отлаживаю и проверяю значение Session для моего ключа, сразу после Clear()
, это дает мне значение ноль. Но когда я передаю Session cookie и пытаюсь прочитать значение, оно снова появляется.
Очевидно, когда Idle Timeout
заканчивается, код ведет себя как ожидалось. В то время это звучит как угроза безопасности.
Любая помощь будет оценена.
РЕДАКТИРОВАТЬ:
Согласно комментарию под постом, я попытался добавить к нему сеанс Redis:
services.AddDistributedRedisCache(setup =>
{
setup.Configuration = "urlToRedisInstance";
setup.InstanceName = "MySessionStateStore2";
});
но поведение точно такое же.
2 ответа
После рытья кода я обнаружил проблему:
Проблема была в моих тестах. Я устанавливал файлы cookie ответа на запрос входа в систему для httpClient "злоумышленника", но не для реального пользователя. В результате он не получил Session Cookie
, Так что мой Session.Clear()
фактически очистил вновь созданный сеанс, а не тот, который был создан во время процесса входа в систему.
Исправленный тест:
var httpClientGenuineRequest = GetClient();
var httpClientAttacker = GetClient();
//Given
var request = new LoginRequest()
{
//filled properties
};
var loginResponse = await httpClientGenuineMember.PostAsync("urlToLoginAction", new JsonContent(request));
AddResponseCookiesToHeaders(httpClientGenuineMember, loginResponse); // THAT LINE MADE THE DIFFERENCE
AddResponseCookiesToHeaders(httpClientAttacker, loginResponse);
await httpClientGenuineMember.PostAsync("urlToLogoutAction", new JsonContent(request));
//When
var response = await httpClientAttacker.GetAsync("urlToCheckStatusAction");
//Here the actual result is true
var actualResult = response.GetResult<bool>();
//Then
var expectedResult = false;
Session.Clear()
работает точно так, как ожидалось.
Причина в том (как бы нелепо это ни звучало) в том, что вы не очищаете правильный сеанс var.
в соответствии с документами Microsoft, сеанс в.net core 2.1 заканчивается, когда происходит один из следующих двух сценариев:
Данные сеанса удаляются либо при вызове реализации ISession.Clear, либо по окончании сеанса.
тогда следующие состояния:
Не существует механизма по умолчанию для информирования кода приложения о том, что браузер клиента был закрыт или когда файл cookie сеанса удален или истек срок его действия на клиенте.
это говорит нам о двух вещах:
1) если вы хотите максимально использовать сеанс с истекшим сроком действия, вам придется самостоятельно настроить механизм для информирования вашего сервера о том, что сеанс клиента истек или браузер закрылся. В противном случае вы рискуете сохранить данные сеанса, даже когда браузер закрыт (это абсурдная ситуация, но она существует).
2) Метод ISession.Clear является частью пространства имен Microsoft.AspNetCore.Http, что означает, что при вызове HttpContext.Session.Clear();
ты вообще ничего не понимаешь вообще.
Как я уже сказал, эта ситуация может быть болезненной, но это живой факт, и наш код должен знать, как с ним справиться, если мы решим работать с.net core 2.1 и состояниями сеанса.