Почему Session.Clear () - не работает? - PullRequest
0 голосов
/ 06 июля 2018

Я использую .NET Core 2.1 и пытаюсь использовать Session как часть аутентификации. Я ожидаю, что это произойдет:

  1. человек входит
  2. Я установил значение сеанса
  3. Сеансовый cookie возвращается
  4. человек клик выйти из системы
  5. Я очищаю сессию к 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(), это дает мне значение null. Но когда я передаю Session cookie и пытаюсь прочитать значение, оно снова появляется.

Очевидно, что когда Idle Timeout заканчивается, код ведет себя как ожидалось. В то время это звучит как угроза безопасности.

Буду признателен за любую помощь.

EDIT:

Согласно комментарию под постом, я попытался добавить к нему сеанс Redis:

services.AddDistributedRedisCache(setup =>
            {
                setup.Configuration = "urlToRedisInstance";
                setup.InstanceName = "MySessionStateStore2";
            });

но поведение точно такое же.

Ответы [ 2 ]

0 голосов
/ 10 июля 2018

После копания кода я обнаружил проблему:

Проблема была в моих тестах. Я устанавливал файлы 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() работает точно так же, как и ожидалось.

0 голосов
/ 10 июля 2018

Причина (как бы нелепо это ни звучало) в том, что вы не очищаете правильный сеанс вар.

в соответствии с документами Microsoft сеанс в .net core 2.1 заканчивается, когда происходит один из следующих двух сценариев:

Данные сеанса удаляются либо при реализации ISession.Clear вызывается или когда истекает сеанс.

тогда следующие состояния:

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

это говорит нам о двух вещах:

1) если вы хотите использовать сеанс с максимальным сроком действия, вам нужно будет самостоятельно механизм, чтобы сообщить вашему серверу, когда сеанс клиента истек или браузер закрыт. В противном случае вы рискуете сохранить данные сеанса, даже когда браузер закрыт (это абсурдная ситуация, но она существует).

2) Метод ISession.Clear является частью Microsoft.AspNetCore.Http пространства имен, что означает, что при вызове HttpContext.Session.Clear(); вы в принципе ничего не понятно вообще.

Как я уже сказал, эта ситуация может быть болезненной, но это живой факт, и наш код должен знать, как с ним обращаться, если мы решим работать с .net core 2.1 и состояниями сеанса.

...