C# AWS Lambda未持久化的.NET核心cookie身份验证

C# AWS Lambda未持久化的.NET核心cookie身份验证,c#,asp.net-core,aws-lambda,asp.net-core-mvc,aws-lambda-edge,C#,Asp.net Core,Aws Lambda,Asp.net Core Mvc,Aws Lambda Edge,我无法使用.NET Core 2.1 MVC使用AWS Lambda函数进行cookie身份验证 我尝试了很多不同的饼干选择。我可以登录并在响应中看到正在创建的asp cookie,但通常在刷新或单击任何链接(例如,服务器的下一个请求)后,我会返回到登录屏幕*更新:看起来我现在的状态是,一开始我只需要登录两次,然后它就会保持登录状态。这也是使用.NET2.1的第二个Lambda函数,我注意到了这种行为 我用默认值配置了API网关,这些默认值是在使用AWS visual studio扩展进行部署时

我无法使用.NET Core 2.1 MVC使用AWS Lambda函数进行cookie身份验证

我尝试了很多不同的饼干选择。我可以登录并在响应中看到正在创建的asp cookie,但通常在刷新或单击任何链接(例如,服务器的下一个请求)后,我会返回到登录屏幕*更新:看起来我现在的状态是,一开始我只需要登录两次,然后它就会保持登录状态。这也是使用.NET2.1的第二个Lambda函数,我注意到了这种行为

我用默认值配置了API网关,这些默认值是在使用AWS visual studio扩展进行部署时设置的

我当前在localhost上运行的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; });

我在登录时也尝试过使用以下方法:

    await HttpContext.SignInAsync(principal, new AuthenticationProperties
    {
        ExpiresUtc = DateTime.UtcNow.AddHours(12),
        IsPersistent = true
    });
简单地使用以下命令将使我保持登录状态,但我必须在cookie持续存在之前登录两次(在单击任何内容并被重定向到再次登录后再次登录):


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

要解决此问题,您需要设置数据保护存储,例如通过(参见文章):

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

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

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


请参见如何在AWS Lambda中为asp.net core配置数据保护。Alex Nazarevych的回答是正确的,因为您需要设置数据保护存储。但是,描述了如何将数据保护密钥存储在AWS Systems Manager参数存储中,而不是存储在文件系统中。这是有意义的,因为Lambda函数将不断退出并丢失其文件存储

我在自己的网站上使用了AWS参数库,它运行得非常好。以下是您需要做的:

  • 在项目中添加对
    Amazon.AspNetCore.DataProtection.SSM
    的NuGet包引用
  • Startup.ConfigureServices
    方法中,添加以下代码。您可以将
    “/DataProtection”
    更改为您喜欢的任何内容;这只是定义了在参数存储中键名的开头:
  • 确保Lambda函数具有AWS参数存储的AddTagsToResourcePutParameterGetParametersByPath权限。作为IAM策略,它将如下所示。请注意,如果您在上面的代码中使用的不是
    “/DataProtection”
    ,则需要更改下面策略中的资源以匹配。(不要忘记结尾的星号。)
  • 代码运行一次后,您可以使用AWS控制台自己查看密钥。只需登录AWS控制台并导航到

        await HttpContext.SignInAsync(principal, new AuthenticationProperties
        {
            ExpiresUtc = DateTime.UtcNow.AddHours(12),
            IsPersistent = true
        });
    
    await HttpContext.SignInAsync(principal);
    
    services.AddDataProtection()
        .PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
        .SetApplicationName("SharedCookieApp");
    
    services.AddDataProtection()
       .PersistKeysToAWSSystemsManager("/DataProtection");
    
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "ssm:AddTagsToResource",
                    "ssm:GetParametersByPath",
                    "ssm:PutParameter"
                ],
                "Resource": "arn:aws:ssm:*:*:parameter/DataProtection*",
                "Effect": "Allow"
            }
        ]
    }