Аутентификация файлов cookie .NET Core с AWS Lambda не сохраняется

Я не могу заставить аутентификацию файлов cookie работать с функцией AWS Lambda, используя .NET Core 2.1 MVC.

Я пробовал множество вариантов файлов cookie. Я могу войти в систему и увидеть, как в ответе создается файл cookie asp, но обычно я возвращаюсь на экран входа в систему после обновления или нажатия на любую ссылку, например. следующий запрос к серверу. * Обновление: кажется, у меня он находится в состоянии, когда мне нужно войти в систему только дважды, и он остается в системе. Это также вторая функция Lambda, использующая .net 2.1, где я заметил это поведение.

У меня есть шлюз API, настроенный по умолчанию, который настраивается при развертывании с использованием расширения AWS для визуальной студии.

Мой текущий код startup.cs, который работает на локальном хосте:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        // Cookie settings
        options.Cookie.SameSite = SameSiteMode.Lax;
        options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
        options.LoginPath = "/Login";
        options.LogoutPath = "/Logout";
        options.AccessDeniedPath = "/Login";
        options.Cookie.Name = "myapp.auth";
        options.Cookie.HttpOnly = true;
        options.Cookie.Expiration = TimeSpan.FromDays(1);
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings, only this changes expiration
        options.SlidingExpiration = true;
        options.ExpireTimeSpan = TimeSpan.FromDays(1);
    });
services.AddAntiforgery(options => { options.Cookie.Expiration = TimeSpan.Zero; });

а также

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseAuthentication();

    app.UseMvc();
}

Я также пытался использовать следующее при входе в систему:

    await HttpContext.SignInAsync(principal, new AuthenticationProperties
    {
        ExpiresUtc = DateTime.UtcNow.AddHours(12),
        IsPersistent = true
    });

Просто используя следующее, я буду оставаться в системе, но мне нужно дважды войти в систему, прежде чем файл cookie сохранится (еще раз после нажатия на что-либо и повторного перенаправления для входа в систему):

await HttpContext.SignInAsync(principal);

person user1854458    schedule 28.04.2019    source источник


Ответы (2)


Это происходит из-за того, что приложение, размещенное в AWS Lambda, периодически ВЫХОДИТ, в результате чего служба DataProtection забывает ваш ключ cookie. Таким образом, даже если ваш клиент приложения отправит файл cookie, сервер отклонит его после перезапуска, поскольку ключ защиты данных изменился.

Для решения проблемы необходимо настроить хранилище защиты данных, т.е. (см. статью в документах MS):

services.AddDataProtection()
    .PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
    .SetApplicationName("SharedCookieApp");

У меня была аналогичная проблема с запуском asp.net core 3.1 на AWS lambda. Когда я проверил журналы, было несколько очень описательных предупреждающих сообщений:

[Предупреждение] Microsoft.AspNetCore.DataProtection.Repositories.EphemeralXmlRepository: использование репозитория в памяти. Ключи не будут сохраняться в хранилище.

[Предупреждение] Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager: ни профиль пользователя, ни реестр HKLM недоступны. Использование хранилища эфемерных ключей. Защищенные данные будут недоступны при выходе из приложения.

См. эту статью. о том, как настроить защиту данных в AWS Lambda для ядра asp.net

person Alex Nazarevych    schedule 28.04.2020

Ответ @Alex Nazarevych правильный в том, что вам нужно настроить хранилище для защиты данных. Однако связанная статья описывает, как хранить ключи защиты данных в хранилище параметров AWS Systems Manager, а не в файловой системе. И это имеет смысл, так как функция Lambda будет постоянно выходить и терять свое файловое хранилище.

Я использую магазин параметров AWS на своем собственном веб-сайте, и он отлично работает. Вот что вам нужно сделать:

  1. Добавьте ссылку на пакет NuGet на Amazon.AspNetCore.DataProtection.SSM в свой проект.
  2. В свой метод Startup.ConfigureServices добавьте следующий код. Вы можете изменить "/DataProtection" на что угодно; это просто определяет, с чего будут начинаться имена ваших ключей в хранилище параметров:
services.AddDataProtection()
   .PersistKeysToAWSSystemsManager("/DataProtection");
  1. Убедитесь, что ваша функция Lambda имеет разрешения AddTagsToResource, PutParameter и GetParametersByPath для хранилища параметров AWS. В качестве IAM-политики это будет выглядеть следующим образом. Обратите внимание: если в приведенном выше коде вы использовали что-то отличное от "/DataProtection", вам необходимо изменить ресурс в приведенной ниже политике, чтобы он соответствовал. (И не забудьте звездочку в конце.)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ssm:AddTagsToResource",
                "ssm:GetParametersByPath",
                "ssm:PutParameter"
            ],
            "Resource": "arn:aws:ssm:*:*:parameter/DataProtection*",
            "Effect": "Allow"
        }
    ]
}

После однократного запуска кода вы можете использовать консоль AWS для самостоятельного просмотра ключей. Просто войдите в консоль AWS и перейдите в хранилище параметров System Manager.

person JamesQMurphy    schedule 23.05.2020