Cookie身份验证问题ASP.NET CORE 2.1。 AWS负载平衡

时间:2019-01-31 17:10:27

标签: c# amazon-web-services authentication asp.net-core-2.1

更新:以下代码似乎失败:

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;
            }

1 个答案:

答案 0 :(得分:1)

好的,现在一切正常。:) 这就是与众不同的原因:

  1. 如果应用处于负载平衡状态,则所有实例必须共享Data Protection加密密钥(例如,使用相同的密钥环)。因此,Redis和一个证书。会话也应该共享。因此,Redis再次出现。

  2. 用于ProtectKeysWithCertificate()调用的
  3. 证书应正确加载。如果无法加载,则根本不会发出该调用,但这确实是个坏主意。只需弄清楚为什么它不加载即可。

  4. 为避免在自定义身份验证HttpContext中引发InvalidOperationException。应该在“登录”操作中手动分配用户。

关于证书的一件重要事情:数据保护模块仅支持带有CAPI私钥的证书。 CNG的被抛在后面。