更新:以下代码似乎失败:
services.AddDataProtection()
.SetApplicationName(appname)
.PersistKeysToRedis(redis, "DataProtectionKeys")
.ProtectKeysWithCertificate(LoadCert(Configuration));
它无法从pfx文件中读取证书。
UPDATE2: 天啊!证书文件已被.gitignore!:)排除在外。至少我们住了,对吧!?))
初始问题: 我在Docker容器中的AWS负载均衡器后面部署了ASP.NET Core 2.1应用程序。 当我尝试从登录页面登录应用程序时。我正在通过以下理由获得InvalidOperationException:
未指定authenticationScheme,并且没有 找到DefaultChallengeScheme。
但是当我再次点击相同的URL时,它实际上会移至正确的页面并运行一段时间,然后再次抛出相同的异常,且HTTP状态为500 在第二次尝试打开同一页面后,它成功。有趣的是,Chrome并不像IE那样强大:如果IE在异常后无法恢复,则Chrome总是在随后提交该页面时返回404,从而产生了上述异常。
因此,如果有人能够为我提供帮助,我将不胜感激 想法如何纠正这种情况显然,问题与 身份验证,但我不知道应该怎么做。
这与Startup.cs中的ConfigureServices()有关:
string appname = "MyApp";
var redis = ConnectionMultiplexer.Connect(Configuration.GetConnectionString("RedisConnection"));
services.AddDataProtection()
.SetApplicationName(appname)
.PersistKeysToRedis(redis, "DataProtectionKeys")
.ProtectKeysWithCertificate(LoadCert(Configuration));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddAuthentication( CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
options =>
{
options.LoginPath = new PathString("/Area/Ctrl/Login");
options.LogoutPath = new PathString("/Area/Ctrl/Logout");
options.Cookie.IsEssential = true;
});
services.AddDistributedRedisCache(o =>
{
o.Configuration = Configuration.GetConnectionString("RedisConnection");
});
services.AddSession(options =>
{
options.Cookie.Name = appname;
options.IdleTimeout = TimeSpan.FromSeconds(600);
});
这是Startup.cs中Configure()的相关代码:
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Ctrl}/{action=Login}/{id?}"
);
});
这是我在控制器中设置负责处理登录的主体的方法:
ClaimsIdentity identity = new ClaimsIdentity(GetUserRoleClaims(dbUserData), CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal principal = new ClaimsPrincipal(identity);
if (principal == null)
throw new ApplicationException($"Could not create principal for {user?.UserName} user.");
await httpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
if (httpContext.User == null)
{
httpContext.User = principal;
}
答案 0 :(得分:1)
好的,现在一切正常。:) 这就是与众不同的原因:
如果应用处于负载平衡状态,则所有实例必须共享Data Protection加密密钥(例如,使用相同的密钥环)。因此,Redis和一个证书。会话也应该共享。因此,Redis再次出现。
ProtectKeysWithCertificate()
调用的证书应正确加载。如果无法加载,则根本不会发出该调用,但这确实是个坏主意。只需弄清楚为什么它不加载即可。
为避免在自定义身份验证HttpContext中引发InvalidOperationException。应该在“登录”操作中手动分配用户。
关于证书的一件重要事情:数据保护模块仅支持带有CAPI私钥的证书。 CNG的被抛在后面。