ASP.NET Основной сеанс истекает слишком рано

#c# #session #asp.net-core

#c# #сессия #asp.net-core

Вопрос:

У меня есть ASP.NET Основное веб-приложение, которое использует сеанс для хранения некоторых переменных. Локально все работает нормально в любом сценарии, но по какой-то причине я не могу получить значения из сеанса в какой-то момент (они равны нулю) на компьютере Azure.

Сценарий:

  1. Выполнение входа в систему, который перенаправляет на другой контроллер (сохранение пользовательских данных в сеансе)
  2. Введите некоторые необходимые данные, а затем перенаправьте на другой контроллер (также сохраняя некоторые данные в сеансе и извлекая другие значения)
  3. На странице индекса задайте дополнительные данные для сеанса. Представление этого контроллера вызывает функцию javascript, которая вызывает «OnScrollEnd«, которая является методом, реализованным этим контроллером.
  4. Когда пользователь прокручивает страницу вниз, вызывается та же функция javascript (которая вызывает OnScrollEnd)
  5. Этот метод пытается извлечь данные из сеанса, но теперь его значение равно null.

(приведенный выше сценарий демонстрирует, что по существу состояние сеанса работает, но в какой-то момент ему не удается получить значения)

Журнал:

2019-04-23 14:12:34,220 [29] ИНФОРМАЦИЯ Microsoft.AspNetCore.Авторизация.DefaultAuthorizationService [(null)] <(null)> — Авторизация прошла успешно. 2019-04-23 14:12:34,220 [29] ИНФОРМАЦИЯ Microsoft.AspNetCore.Авторизация.DefaultAuthorizationService [(null)] <(null)> — Авторизация прошла успешно. 2019-04-23 14:12:34,220 [29] ИНФОРМАЦИЯ Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [(null)] <(null)> — Выполнение метода действия MyWebService.Контроллеры.AllCardsController.OnScrollEnd (MyWebService) — Состояние проверки: действительное 2019-04-23 14:12:34,220 [29] ИНФОРМАЦИЯ Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [(null)] <(null)> — Выполнение метода действия MyWebService.Контроллеры.AllCardsController.OnScrollEnd (MyWebService) — Состояние проверки: действительное 2019-04-23 14:12:34,220 [29] ИНФОРМАЦИЯ Microsoft.AspNetCore.Session.DistributedSession [(null)] <(null)> — Доступ к сеансу с истекшим сроком действия, ключ: c691acb5-f9ed-5a71-6ebb-f3a0980c4efd 2019-04-23 14:12:34,220 [29] ИНФОРМАЦИЯ Microsoft.AspNetCore.Session.DistributedSession [(null)] <(null)> — Доступ к сеансу с истекшим сроком действия, ключ: c691acb5-f9ed-5a71-6ebb-f3a0980c4efd 2019-04-23 14:12:34,221 [29] ИНФОРМАЦИЯ Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [(null)] <(null)> — Выполнено действие MyWebService.Контроллеры.AllCardsController.OnScrollEnd (MyWebService) через 0,7545мс 2019-04-23 14:12:34,221 [29] ИНФОРМАЦИЯ Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker [(null)] <(null)> — Выполнено действие MyWebService.Контроллеры.AllCardsController.OnScrollEnd (MyWebService) через 0,7545мс 2019-04-23 14:12:34,223 [29] ОШИБКА Microsoft.AspNetCore.Диагностика.ExceptionHandlerMiddleware [(null)] <(null)> — При выполнении запроса произошло необработанное исключение.

(Исключение возникает из-за того, что значение, полученное из сеанса, было нулевым)

Конфигурация запуска:

         public void ConfigureServices(IServiceCollection services)
        {
            var expiredSessionHours = Configuration.GetValue<int>("SessionExpireHours");
            var expiredSessionMinutes = Configuration.GetValue<int>("SessionExpireMinutes");

            services.AddLocalization(options => options.ResourcesPath = "Resources");

            services.AddAuthentication(options =>
            {
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie(options =>
            {
                options.LoginPath = "/Login";
                options.ExpireTimeSpan = new TimeSpan(expiredSessionHours, expiredSessionMinutes, 0);
                options.SlidingExpiration = true;
                options.Cookie.Expiration = new TimeSpan(expiredSessionHours, expiredSessionMinutes, 0);
            });

            services.AddScoped<IUserAuthentication, AuthenticationService>();
            services.AddTransient<IEncryptionService, EncryptionService>();
            services.AddDbContext<DatabaseContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("myConnectionString"))
                    .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking), 
                ServiceLifetime.Transient);

            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => false;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddDistributedMemoryCache();
            services.AddSession(options =>
            {
                options.Cookie.HttpOnly = true;
                options.Cookie.IsEssential = true;
                options.IdleTimeout = new TimeSpan(expiredSessionHours, expiredSessionMinutes, 0);
            });

            services.AddMvc(options =>
                {
                    var policy = new AuthorizationPolicyBuilder()
                        .RequireAuthenticatedUser()
                        .Build();
                    options.Filters.Add(new AuthorizeFilter(policy));
                })
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        // Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
        {
            if (HostingEnvironment.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

            var supportedCultures = new[]
            {
                new CultureInfo("en-US"),
            };

            app.UseRequestLocalization(new RequestLocalizationOptions
            {
                DefaultRequestCulture = new RequestCulture("en-US"),
                SupportedCultures = supportedCultures,
                SupportedUICultures = supportedCultures
            });

            loggerFactory.AddLog4Net();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseSession();
            app.UseAuthentication();
            app.UseMvc();
        }
  

Комментарии:

1. Вы проверили эти значения в отладчике? Истекшие сессионные часы и истекшие сессионные минуты?

2. Azure закрывает соединение, когда оно простаивает. Поэтому вам может потребоваться включить в вашем клиенте функцию Keep-Alive, которая будет периодически отправлять пустое сообщение в Azure, чтобы Azure не закрывала соединение.

3. @Jon — Да, они установлены на 1 час

4. @jdweng Как мне это сделать?

5. Не уверен, какие методы использует ваш клиент. Возможна настройка SetHandlerLifetime. Смотрите: learn.microsoft.com/en-us/aspnet/core/fundamentals /…