5

我无法通过使用 .NET Core 2.1 MVC 的 AWS Lambda 函数获得 cookie 身份验证。

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

我配置了 API 网关,并在使用 AWS 扩展为 Visual Studio 进行部署时设置了默认值。

我当前的 startup.cs 代码,可在 localhost 上运行:

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

2 回答 2

2

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

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

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

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

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

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

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

于 2020-04-28T08:41:29.593 回答
2

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

我在自己的网站上使用 AWS Parameter store,它运行良好。这是您需要做的:

  1. 将 NuGet 包引用添加Amazon.AspNetCore.DataProtection.SSM到您的项目。
  2. 在您的Startup.ConfigureServices方法中,添加以下代码。您可以将其更改"/DataProtection"为您喜欢的任何内容;这只是定义了您的键名将在 Parameter Store 中以什么开头:
services.AddDataProtection()
   .PersistKeysToAWSSystemsManager("/DataProtection");
  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"
        }
    ]
}

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

于 2020-05-23T02:45:20.143 回答