Сеанс пользователя .Net Core 2.x неожиданно завершает работу на Shared Hosting - PullRequest
0 голосов
/ 24 января 2019

Я играю с шаблоном 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. Я собираюсь дать ему поработать некоторое время, и если все будет хорошо, я опубликую решение и как оно было реализовано.

Ответы [ 3 ]

0 голосов
/ 25 января 2019

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

0 голосов
/ 16 апреля 2019

Проблема, как оказалось, не в том, что сеанс истекает, а, скорее, когда другой сервер принимает на себя нагрузку на мой сайт, у него нет контекста сеанса.Службы защиты данных позволяют создавать базу данных, в которой хранится информация о сеансе, и она распределяется между серверами фермы.Аналогично атрибуту состояния сеанса из 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), но, поскольку у меня нет контроля над сервером, мой сайтСлужба защиты данных работает нормально.

0 голосов
/ 24 января 2019

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

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

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

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

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

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