Проблема проверки подлинности cookie ASP.NET CORE 2.1.Распределение нагрузки AWS - PullRequest
0 голосов
/ 31 января 2019

ОБНОВЛЕНИЕ: Похоже, что следующий код не работает:

services.AddDataProtection()
            .SetApplicationName(appname)
            .PersistKeysToRedis(redis, "DataProtectionKeys")
            .ProtectKeysWithCertificate(LoadCert(Configuration));

Невозможно прочитать сертификат из файла pfx.

ОБНОВЛЕНИЕ2: О боже!Файл сертификата был исключен .gitignore! :)) Live & Learn.По крайней мере, мы жили, не так ли?Когда я пытаюсь войти в приложение со страницы входа.Я получаю InvalidOperationException с этим обоснованием:

Не указана схема authenticationScheme, и не найдено DefaultChallengeScheme.

Но когда я снова нажимаю тот же URL, он фактически переходит ксоответствующая страница и работает некоторое время, затем снова выдает то же исключение со статусом HTTP 500 и после 2-й попытки открыть ту же страницу, это успешно.Интересно, что Chrome не так надежен, как IE: если IE не удается восстановить после исключения, Chrome всегда возвращает 404 при последующем представлении страницы, которая вызвала вышеупомянутое исключение.

Поэтому я был бы признателен, если бы кто-тобыть в состоянии предоставить мне идеи, как исправить ситуацию. Очевидно, что проблема связана с аутентификацией, но я не мог понять, что именно должно быть сделано.

Вот соответствующий пример из ConfigureServices () вStartup.cs:

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

Вот соответствующий код из Configure () в Startup.cs:

        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 голосов
/ 01 февраля 2019

Хорошо, теперь все работает. :) Вот что изменило:

  1. Если приложение находится под балансировкой нагрузки, все экземпляры должны совместно использовать ключи шифрования защиты данных (например, использовать один и тот же).брелок для ключей).Отсюда приходит Redis и сертификат.Сессия также должна быть общедоступной.Отсюда снова приходит Redis.

  2. Сертификат для вызова ProtectKeysWithCertificate() должен загружаться правильно.Если он не может быть загружен, не делайте этот вызов вообще, но это было бы действительно плохой идеей.Просто выясните, почему он не загружается.

  3. Чтобы исключить InvalidOperationException в пользовательской аутентификации HttpContext.Пользователь должен быть назначен вручную внутри действия входа в систему.

Одна важная вещь о сертификате: модуль защиты данных поддерживает только сертификаты с закрытыми ключами CAPI.КПГ остались позади.

...