我们最近将我们的 .net 核心应用程序部署到负载均衡的生产环境中。用户报告说该网站间歇性地死掉——通常在 20 到 30 分钟后。应用程序无法再从数据库中获取数据,用户被迫再次登录。它似乎最常发生在交通繁忙的时期。
在部署之前,该应用程序在负载平衡的服务器上进行了测试,一切都按预期工作。
查看应用程序的日志,我看到以下消息:
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler[7]
Cookies was not authenticated. Failure message: Unprotect ticket failed
我在想数据保护的设置方式可能有问题。它目前使用数据库上下文方案。
这是中间件的样子:
public void ConfigureServices(IServiceCollection services)
{
// Add a DbContext to store the Database Keys
services.AddDbContext<DatabaseContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DataProtection")));
// using Microsoft.AspNetCore.DataProtection;
services.AddDataProtection()
.PersistKeysToDbContext<DatabaseContext>();
services.AddCors(options =>
{
options.AddPolicy("AllowAll",
builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
services.Configure<EnvironmentSettings>(options => Configuration.GetSection("EnvironmentSettings").Bind(options));
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false;
options.MinimumSameSitePolicy = SameSiteMode.None;
options.Secure = CookieSecurePolicy.SameAsRequest;
});
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme;
})
.AddCookie(cookieOptions =>
{
cookieOptions.AccessDeniedPath = "/AccessDenied";
cookieOptions.ExpireTimeSpan = TimeSpan.FromMinutes(Convert.ToDouble(Configuration["wsfed:cookieTimeout"]));
cookieOptions.Cookie.SameSite = SameSiteMode.None;
cookieOptions.Cookie.Name = "FedAuth";
cookieOptions.Cookie.HttpOnly = true;
cookieOptions.Cookie.IsEssential = true;
})
.AddWsFederation(options =>
{
options.Wtrealm = Configuration["wsfed:realm"];
options.MetadataAddress = Configuration["wsfed:metadata"];
options.AllowUnsolicitedLogins = true;
options.CorrelationCookie.SameSite = SameSiteMode.None;
options.Events.OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.Wct = DateTimeOffset.UtcNow.ToString();
return Task.CompletedTask;
};
options.Events.OnSecurityTokenValidated += context =>
{
context.Properties.RedirectUri = Configuration["wsfed:redirecturi"];
return Task.CompletedTask;
};
options.Events.OnRemoteFailure += context =>
{
context.HandleResponse();
if (context.Failure.Message == "Correlation failed.")
{
context.Response.Redirect(Configuration["wsfed:realm"]);
}
return Task.CompletedTask;
};
});
数据库上下文类:
public class DatabaseContext : DbContext, IDataProtectionKeyContext
{
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { }
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
}
以下是我们迄今为止尝试过的事情的列表:
- 检查数据库中的 DataProtectionKeys 表是否有过期密钥。一切看起来都很好。
- IIS:AppPool 将空闲超时设置为 0,启动模式设置为“始终运行”,启用预加载 = True
- 尝试通过在应用程序处于活动状态时关闭负载平衡来复制暂存中的问题。没有看到任何问题,该应用程序保持与数据库的连接并继续工作。
- 清除缓存以删除现有 cookie
关于什么可能是错误的任何想法?