使用 AWS Lambda 的 .NET Core cookie 身份验证未持久

use*_*458 7 c# asp.net-core-mvc aws-lambda asp.net-core aws-lambda-edge

我无法使用 .NET Core 2.1 MVC 与 AWS Lambda 函数一起使用 cookie 身份验证。

我尝试过很多 cookie 选项的变体。我能够登录并看到在响应中创建的 asp cookie,但通常在刷新或单击任何链接(例如对服务器的下一个请求)后,我会返回到登录屏幕。*更新:看来我现在只需要登录两次并且保持登录状态。这也是使用 .net 2.1 的第二个 Lambda 函数,我注意到了这种行为。

我已经配置了 API 网关,该网关使用使用适用于 Visual Studio 的 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; });
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

我在登录时也尝试使用以下内容:

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

只需使用以下命令即可让我保持登录状态,但在 cookie 持续存在之前我必须登录两次(在单击任何内容并被重定向到再次登录后再次登录):

await HttpContext.SignInAsync(principal);
Run Code Online (Sandbox Code Playgroud)

Jam*_*phy 6

@Alex Nazarevych 的答案是正确的,因为您需要设置数据保护存储。但是,链接的文章介绍了如何将数据保护密钥存储在 AWS Systems Manager Parameter Store 中,而不是文件系统中。这是有道理的,因为 Lambda 函数将不断退出并丢失其文件存储。

我在自己的网站上使用 AWS 参数存储,它运行得非常好。您需要执行以下操作:

  1. 将 NuGet 包引用添加到Amazon.AspNetCore.DataProtection.SSM您的项目。
  2. 在您的Startup.ConfigureServices方法中,添加以下代码。您可以将其更改"/DataProtection"为您喜欢的任何内容;这只是定义您的键名称在参数存储中以什么开头:
services.AddDataProtection()
   .PersistKeysToAWSSystemsManager("/DataProtection");
Run Code Online (Sandbox Code Playgroud)
  1. 确保您的 Lambda 函数具有AWS Parameter Store 的AddTagsToResourcePutParameterGetParametersByPath权限。作为 IAM 策略,它看起来如下所示。请注意,如果您使用了上面代码中以外的其他内容"/DataProtection",则需要更改下面策略中的资源以匹配。(不要忘记最后的星号。)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ssm:AddTagsToResource",
                "ssm:GetParametersByPath",
                "ssm:PutParameter"
            ],
            "Resource": "arn:aws:ssm:*:*:parameter/DataProtection*",
            "Effect": "Allow"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

代码运行一次后,您可以使用 AWS 控制台自行查看密钥。只需登录 AWS 控制台并导航至Systems Manager Parameter Store即可。

  • 我花了整整一周 12 多个小时试图弄清楚为什么在 AWS Lambda 上使用 .net core 6 时 AJAX 调用不起作用 - 这就是解决方案。主要感谢@James! (2认同)

Ale*_*ych 3

发生这种情况是因为 AWS Lambda 中托管的应用程序定期退出,导致 DataProtection 服务忘记您的 cookie 密钥。因此,即使您的应用程序客户端确实发送了 cookie,服务器在重新启动后也会拒绝它,因为数据保护密钥已更改。

要解决该问题,您需要设置数据保护存储,例如(请参阅ms docs 上的文章):

services.AddDataProtection()
    .PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
    .SetApplicationName("SharedCookieApp");
Run Code Online (Sandbox Code Playgroud)

我在 AWS lambda 上运行 asp.net core 3.1 时遇到了类似的问题。当我检查日志时,有几条非常具有描述性的警告消息:

[警告] Microsoft.AspNetCore.DataProtection.Repositories.EphemeralXmlRepository:使用内存存储库。密钥不会持久保存到存储中。

[警告] Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager:用户配置文件和 HKLM 注册表均不可用。使用临时密钥存储库。当应用程序退出时,受保护的数据将不可用。

请参阅这篇文章,了解如何在 AWS Lambda 中为 asp.net core 配置 DataProtection