Сеанс пользователя.Net Core 2.x неожиданно завершает работу на Shared Hosting

Я играю с шаблоном aspnetboilerplate.com для ядра dotnet. Я пытаюсь развернуть шаблон на сервере общего хостинга (windows) под управлением Plesk (обратите внимание, я вообще не контролирую сервер).

Шаблон отлично работает локально, может входить в систему, добавлять пользователей, роли и т. Д. При его развертывании на сервере общего хостинга возникли некоторые проблемы, но это было решено относительно быстро (настройка для ядра dotnet и пришлось перейти на ядро ​​dotnet 2.1, так как 2.2 не пока поддерживается на сервере).

Проблема сейчас в том, что после входа в систему, через минуту я перенаправил на страницу входа. У меня была похожая проблема с ASP.NET MVC5, но предоставление машинного ключа в web.config и использование базы данных для данных сеанса устранило эту проблему. Поэтому я полагаю, что это та же проблема с приложением dotnet.

Но поскольку ядро ​​dotnet не использует машинные ключи и DataProtectionApis, необходим другой подход.

Итак, я попытался добавить services.AddDataProtection(); в StartUp.Configure()

Я прочитал Распределенное кеширование в ASP.NET Core и почти все ссылки там, а также попробовал несколько примеров кода, но либо я не знаю, что я делаю (высокая вероятность), либо я делаю что-то не так.

Итак, как я могу предотвратить неожиданный выход пользователя из системы с помощью dotnet core 2.1 на сервере общего хостинга?

РЕДАКТИРОВАТЬ - 2019-01-25

Некоторая новая информация: Попытка установить тайм-ауты как предложено, но это либо ничего не делает, либо невозможно. Чтобы приложение dotnet работало на Plesk, мне пришлось отключить поддержку ASP.NET, чтобы ядро ​​.NET получило пул приложений без управляемого кода. Попытка получить доступ к настройкам ASP.Net в Plesk (где у вас будет доступ к настройке пула приложений и т. Д.) Приводит к ошибке "Поддержка ASP.NET для этого веб-сайта".

Единственное, чего не происходит, это то, что папка App_Data/Logs никогда не создается при публикации. Мне пришлось вручную создавать и устанавливать разрешения, чтобы log4net мог создать файл журнала. Файл журнала предоставил мне дополнительную информацию:

ERROR 2019-01-25 09:33:03,005 [6    ] .Antiforgery.Internal.DefaultAntiforgery - An exception was thrown while deserializing the token.
Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The antiforgery token could not be decrypted. ---> System.Security.Cryptography.CryptographicException: The key {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} was not found in the key ring.

Поиск этой ошибки только еще раз привел меня к документации о добавлении services.AddDataProtection() к методу ConfigureServices, но это напоминает о хранилищах ключей Azure (или других внешних провайдерах) или записи информации в общий UNC, чтобы другие серверы могли получить доступ к информации из кэшированного ключа (и это, вероятно, то, что мне нужно). Но, поскольку все эти опции мне недоступны, я нашел метод расширения, который позволяет хранить ключ на сервере MSSQL. Занят, настраивая это сейчас, чтобы проверить.

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

ОБНОВЛЕНИЕ 2 - 2019-01-25 - УСПЕХ (пока)

Казалось бы, использование DataProtectionAPI - это путь. Логи не сообщают ни о каких AntiforgeryValidationException, еще. Я собираюсь дать ему поработать некоторое время, и если все будет хорошо, я опубликую решение и как оно было реализовано.

2 ответа

Как PersistKeysToSqlServer не поддерживается в dot net core 3.1, мы можем использовать .PersistKeysToDbContext<AppDBContext>() или PersistKeysToFileSystemкак показано здесь.

Исходя из информации, которую вы предоставили выше, я считаю, что ваше заседание истекло.

Когда время сеанса истечет, пользователь будет перенаправлен на страницу входа для повторной аутентификации. Я не слишком знаком с plesk, но из-за очень быстрого поиска в Google кажется, что вы сможете увеличить время ожидания сессии.

Конечно, если вы устанавливаете время ожидания сеанса самостоятельно в configurservices, вы можете просто настроить его там, как я полагаю (опять же, незнакомый с настройкой plesk полностью).

Если вы это сделаете, проблема должна разрешиться сама собой. Возможно, время ожидания сеанса установлено на короткий период времени для тестирования?

состояние сеанса.net

services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromSeconds(10);
            options.Cookie.HttpOnly = true;
        });

Общий хостинг имеет некоторые ограничения для вашего пула приложений. Вы можете проверить значение "Idle Timeout" на панели инструментов Plesk. Поэтому в главной панели инструментов нажмите "Пул выделенных приложений для веб-сайта" и проверьте указанное значение. Я не уверен в том, что установка времени ожидания простоя через ваш код решает вашу проблему, но поддержка поставщика услуг может легко установить его для вас на пользовательское значение.

Оказывается, проблема была не в истечении сеанса, а в том, что когда другой сервер принимает на себя нагрузку на мой сайт, у него нет контекста сеанса. Службы защиты данных позволяют создавать базу данных, в которой хранится информация о сеансе, и она распределяется между серверами в ферме. Аналогично атрибуту состояния сеанса из web.config в проектах MVC:

<sessionState mode="SQLServer" sqlConnectionString="Data Source=000.000.000.000;Initial Catalog=session_db;User Id=user;Password=password;" allowCustomSqlDatabase="true" timeout="480" />

Вот как я решил проблему:

В ConfigureServices я добавил:

services.AddDataProtection()
            .SetApplicationName("MyApplicationName")
            .SetDefaultKeyLifetime(TimeSpan.FromDays(14)) 
            .PersistKeysToSqlServer(_config["DataProtection:SqlServerConnectionString"]);

Мне также пришлось создать отдельную базу данных, которая отвечает за хранение информации о сеансе. DataProtextion:SqlServerConnectionString это запись в appsettings.json файл:

"DataProtection":
    {
        "SqlServerConnectionString": "Server=server; Database=database; User=user; Password=password;"
    }

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

Другие вопросы по тегам