.Net Core 2.x 用户会话意外退出共享主机
.Net Core 2.x User Session signs out on Shared Hosting unexpectedly
我正在使用 aspnetboilerplate.com's dotnet 核心模板。我想做的是将模板部署到共享主机 (windows) 服务器 运行ning Plesk(注意,我根本无法控制服务器)。
该模板在本地完美运行,可以登录、添加用户、角色等。将其部署到共享托管服务器时出现了一些问题,但问题解决得相对较快(针对 dotnet 核心进行配置,不得不转到 dotnet 核心2.1 因为服务器尚不支持 2.2)。
现在的问题是登录后,一分钟内我重定向到登录页面。我在使用 ASP.NET MVC5 时遇到了类似的问题,但是在 web.config 中提供了一个机器密钥并为会话数据使用数据库解决了这个问题。所以我推断它与 dotnet 应用程序存在相同的问题。
但是由于 dotnet 核心不使用机器密钥和 DataProtectionApis,因此需要一种不同的方法。
所以我尝试将 services.AddDataProtection();
添加到 StartUp.Configure()
我已经阅读了 Distributed caching in ASP.NET Core 并且几乎所有的链接都在那里,并且尝试了多个代码示例,但是我不知道我在做什么(很可能)或者我没有做某事对。
那么,如何防止用户在共享托管服务器上使用 dotnet core 2.1 意外注销?
编辑 - 2019-01-25
一些新信息:已尝试按照建议设置超时,但这要么无济于事,要么不可能。对于 Plesk 上 运行 的 dotnet 应用程序,我必须禁用 ASP.NET 支持,以便 .NET 核心获得无托管代码应用程序池。尝试访问 Plesk 上的 ASP.Net 设置(您可以在其中访问应用程序池设置等)给出一个错误提示 'ASP.NET support is switched off for this website'。
有一件事不会发生,那就是发布时从未创建 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 Key Vaults(或其他外部提供商)或将信息写入共享 UNC 所以其他服务器可以访问缓存的密钥信息(这可能是我需要的)。但鉴于我无法使用所有这些选项,我找到了一种扩展方法,它允许将密钥存储在 MSSQL 服务器上。现在忙着设置这个来测试。
如果有人想发表意见,请做客
更新 2 - 2019-01-25 - 成功(目前)
看来使用 DataProtectionAPI 是可行的方法。日志尚未报告任何 AntiforgeryValidationException
。我打算让它 运行 一段时间,如果一切顺利,我将 post 解决方案及其实施方式。
根据您在上面提供的信息,我认为您的会话超时了。
当会话超时时,用户将被重定向到登录页面以重新进行身份验证。我对 plesk 不是很熟悉,但是从非常快速的谷歌搜索看来,您应该能够增加会话超时。
当然,如果您在 configurservices 中自己设置 sessiontimeout,我认为您也可以在那里进行调整(再次完全不熟悉 plesk 设置)。
如果您这样做,问题应该会自行解决。也许会话超时设置为测试的短时间?
.net 会话状态
services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
});
问题,事实证明不是会话过期,而是当另一台服务器接管我的站点的负载时,它没有会话上下文。数据保护服务允许创建一个数据库来存储会话信息,并在场中的服务器之间共享。类似于 MVC 项目中 web.config 的会话状态属性:
<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),但鉴于我无法控制我的网站所在的服务器,数据保护服务工作得很好。
由于 dot net core 3.1 不支持 PersistKeysToSqlServer
,我们可以使用 .PersistKeysToDbContext<AppDBContext>()
或 PersistKeysToFileSystem
,如图所示 here。
我正在使用 aspnetboilerplate.com's dotnet 核心模板。我想做的是将模板部署到共享主机 (windows) 服务器 运行ning Plesk(注意,我根本无法控制服务器)。
该模板在本地完美运行,可以登录、添加用户、角色等。将其部署到共享托管服务器时出现了一些问题,但问题解决得相对较快(针对 dotnet 核心进行配置,不得不转到 dotnet 核心2.1 因为服务器尚不支持 2.2)。
现在的问题是登录后,一分钟内我重定向到登录页面。我在使用 ASP.NET MVC5 时遇到了类似的问题,但是在 web.config 中提供了一个机器密钥并为会话数据使用数据库解决了这个问题。所以我推断它与 dotnet 应用程序存在相同的问题。
但是由于 dotnet 核心不使用机器密钥和 DataProtectionApis,因此需要一种不同的方法。
所以我尝试将 services.AddDataProtection();
添加到 StartUp.Configure()
我已经阅读了 Distributed caching in ASP.NET Core 并且几乎所有的链接都在那里,并且尝试了多个代码示例,但是我不知道我在做什么(很可能)或者我没有做某事对。
那么,如何防止用户在共享托管服务器上使用 dotnet core 2.1 意外注销?
编辑 - 2019-01-25
一些新信息:已尝试按照建议设置超时,但这要么无济于事,要么不可能。对于 Plesk 上 运行 的 dotnet 应用程序,我必须禁用 ASP.NET 支持,以便 .NET 核心获得无托管代码应用程序池。尝试访问 Plesk 上的 ASP.Net 设置(您可以在其中访问应用程序池设置等)给出一个错误提示 'ASP.NET support is switched off for this website'。
有一件事不会发生,那就是发布时从未创建 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 Key Vaults(或其他外部提供商)或将信息写入共享 UNC 所以其他服务器可以访问缓存的密钥信息(这可能是我需要的)。但鉴于我无法使用所有这些选项,我找到了一种扩展方法,它允许将密钥存储在 MSSQL 服务器上。现在忙着设置这个来测试。
如果有人想发表意见,请做客
更新 2 - 2019-01-25 - 成功(目前)
看来使用 DataProtectionAPI 是可行的方法。日志尚未报告任何 AntiforgeryValidationException
。我打算让它 运行 一段时间,如果一切顺利,我将 post 解决方案及其实施方式。
根据您在上面提供的信息,我认为您的会话超时了。
当会话超时时,用户将被重定向到登录页面以重新进行身份验证。我对 plesk 不是很熟悉,但是从非常快速的谷歌搜索看来,您应该能够增加会话超时。
当然,如果您在 configurservices 中自己设置 sessiontimeout,我认为您也可以在那里进行调整(再次完全不熟悉 plesk 设置)。
如果您这样做,问题应该会自行解决。也许会话超时设置为测试的短时间?
.net 会话状态
services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
});
问题,事实证明不是会话过期,而是当另一台服务器接管我的站点的负载时,它没有会话上下文。数据保护服务允许创建一个数据库来存储会话信息,并在场中的服务器之间共享。类似于 MVC 项目中 web.config 的会话状态属性:
<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),但鉴于我无法控制我的网站所在的服务器,数据保护服务工作得很好。
由于 dot net core 3.1 不支持 PersistKeysToSqlServer
,我们可以使用 .PersistKeysToDbContext<AppDBContext>()
或 PersistKeysToFileSystem
,如图所示 here。