如何更改“.AspNetCore.Identity.Application” cookie的过期时间?

11
我正在使用ASP.NET Core与Identity Server和Open Id Connect,如这里所述。当设置了“记住我”选项时,我需要更改身份验证Cookie的过期时间(默认为14天)。我可以看到名为“.AspNetCore.Identity.Application”的Cookie负责此事。我尝试像这样设置过期时间:
.AddCookie(options =>
{
    options.Cookie.Expiration = TimeSpan.FromDays(1);
    options.ExpireTimeSpan = TimeSpan.FromDays(1);
})

但它会影响另一个名为".AspNetCore.Cookies"的cookie(包含相同的令牌值),该cookie具有会话过期并且似乎没有任何作用。我找到的所有更改过期时间的方法都只修改了".AspNetCore.Cookies" cookie,我找不到任何修改".AspNetCore.Identity.Application" cookie的方法。(顺便说一下,由于某种原因,对我来说services.ConfigureApplicationCookie方法根本没有触发)。
请问有人可以解释一下这两个cookie之间的区别,以及我如何修改".AspNetCore.Identity.Application"的过期时间吗?
我的代码在Startup.ConfigureServices中。
services.AddMvc(options =>
{
    // ...
})

services.AddAuthorization(options =>
{
    options.AddPolicy(PolicyNames.UserPolicy, policyBuilder =>
    {
        // ... 
    });
});

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie(options =>
{
    options.AccessDeniedPath = "/AccessDenied";
    options.SlidingExpiration = true;
})
.AddOpenIdConnect("oidc", options =>
{
    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.Authority = "<authority>";
    options.RequireHttpsMetadata = false;
    options.ClientId = "<id>";
    options.ClientSecret = "<secret>";
    options.ResponseType = "code id_token";
    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;
    // ...
});

services.ConfigureApplicationCookie(options =>
{
    options.Cookie.Name = "MyCookie";
    options.Cookie.Expiration = TimeSpan.FromDays(1);
    options.ExpireTimeSpan = TimeSpan.FromDays(1);
});

谢谢,但我仍然有问题。就像我说的那样,在services.ConfigureApplicationCookie方法中设置选项根本没有被调用。 - zdev
我已经将代码添加到问题中。原因可能是调用AddMvcAddAuthenticationConfigureApplicationCookie的顺序吗? - zdev
你的代码似乎根本没有使用身份验证。 - Kirk Larkin
我不确定您所说的Identity是什么意思,它没有调用AddIdentity吗?它使用OIDC,如此处所述。从IdentityServer(OpenIdConnectOptions.Authority)获取身份验证令牌。还有一个链接指向我在问题开头使用的示例。 - zdev
2
“.AspNetCore.Identity.Application” cookie是Identity使用的。由于您没有使用Identity,因此不清楚为什么会有这个cookie。也许您应该查看您的Identity Server项目,我猜它正在使用Identity并设置该cookie。 - Kirk Larkin
这个回答解决了你的问题吗?IdentityServer4如何设置服务器cookie过期时间 - Daniel P
4个回答

10

正如 Kirk Larkin 所说,".AspNetCore.Identity.Application" cookie 可能由使用 Asp.Net Identity 的 Identity Server 应用程序设置。因此,如果您想在 IS4 应用程序上管理用户会话,则需要在那里进行配置。

IS4 应用程序:".AspNetCore.Identity.Application" cookie。

如果您使用 Identity 将 cookie 配置为持久性,则需要在用户登录时设置过期时间。

var props = new AuthenticationProperties {
  IsPersistent = true,
  ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
};
await HttpContext.SignInAsync(userId, userName, props);

如果您不设置 IsPersistent=true,那么cookie的生命周期为会话级别,并且可以使用以下方式设置所包含的身份验证票据的过期时间:
.AddCookie(options => {
    options.Cookie.Name = "idsrv_identity";
    options.ExpireTimeSpan = TimeSpan.FromHours(8);
    options.SlidingExpiration = true;
  });

您的客户端应用程序:".AspNetCore.Cookies" cookie。

services.ConfigureApplicationCookie 没有被调用,因为如果使用 .AddCookie(...),它将具有优先权。选项是相同的。

这将设置应用程序cookie作为会话

.AddCookie(options => {
    options.Cookie.Name = "myappcookie";
    options.ExpireTimeSpan = TimeSpan.FromHours(8);
    options.SlidingExpiration = true;
  });

使用OIDC使应用程序cookie持久化的方法是在AddCookie中的OnSigningIn事件中设置到期时间。
options.Events.OnSigningIn = (context) =>
{
    context.CookieOptions.Expires = DateTimeOffset.UtcNow.AddDays(30);
    return Task.CompletedTask;
};

关于用户会话的说明。

每种情况都不同,因此没有最佳解决方案。但请记住,您必须处理两个用户会话,一个在IS4应用程序上,另一个在您的客户端应用程序上。 这些会话可能会不同步。 您需要考虑在客户端应用程序中持续存在用户会话是否有意义。 当中央SSO(单一登录)会话过期时,您不希望用户在客户端应用程序中保持已登录状态。


这对外部用户如何运作?_signInManager.ExternalLoginSignInAsync(loginProvider, providerKey, isPersistent: false, true); 这个方法不包含设置本地用户过期时间的参数。 - Gopal Zadafiya
@GopalZadafiya 这个例子使用 IdentityServer,因此外部登录是在 IdentityServer 应用程序中而不是在客户端中进行管理的。但一般来说,您可以在配置中设置过期时间,例如,如果使用 Identity,则可以在 AddIdentity 中设置,在 AddCookie 或 AddCookieAuthentication 中也是如此。我从未使用过外部登录,所以无法更具体地说明,请查阅 asp.net core 文档。 - sevenmy

7
在研究了AspNetCore 3.1IdentityServer 4.0.4仓库之后,我找到了设置默认身份验证cookie选项的工作方法。 简称:
    // in Startup.ConfigureService(IServiceCollection services)
    services.PostConfigure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme, option =>
    {
        option.Cookie.Name = "Hello"; // change cookie name
        option.ExpireTimeSpan = TimeSpan.FromSeconds(30); // change cookie expire time span
    });

完整设置:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddRazorPages();

        // cookie policy to deal with temporary browser incompatibilities
        services.AddSameSiteCookiePolicy();
        services.AddDefaultAllowAllCors();

        // setting up dbcontext for stores;
        services.AddDbContext<ApplicationDbContext>(ConfigureDbContext);

        services
            .AddIdentity<ApplicationUser, IdentityRole>(options =>
            {
                options.SignIn.RequireConfirmedAccount = true;
            })
            .AddEntityFrameworkStores<ApplicationDbContext>()
            .AddDefaultUI()
            .AddDefaultTokenProviders();

        // read clients from https://dev59.com/ZlYO5IYBdhLWcg3wU_6M#54892390
        var builder = services.AddIdentityServer(options =>
        {
            options.Events.RaiseSuccessEvents = true;
            options.Events.RaiseFailureEvents = true;
            options.Events.RaiseErrorEvents = true;
            options.Events.RaiseInformationEvents = true;
            options.UserInteraction.LoginUrl = "/identity/account/login";
            options.IssuerUri = _configuration.GetValue<string>("IdentityServer:IssuerUri");
        })

            .AddAspNetIdentity<ApplicationUser>()
            .AddDeveloperSigningCredential()
            .AddConfigurationStore<ApplicationConfigurationDbContext>(option => option.ConfigureDbContext = ConfigureDbContext)
            .AddOperationalStore<ApplicationPersistedGrantDbContext>(option => { option.ConfigureDbContext = ConfigureDbContext; })
            .AddJwtBearerClientAuthentication()
            .AddProfileService<ApplicationUserProfileService>();

        services.PostConfigure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme, option =>
        {
            option.Cookie.Name = "Hello";
            option.ExpireTimeSpan = TimeSpan.FromSeconds(30);
        });
        services.AddScoped<Microsoft.AspNetCore.Identity.UI.Services.IEmailSender, EmailSender>();
        services.Configure<SmsOption>(_configuration);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // use this for persisted grants store
        InitializeDatabase(app);

        app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
        });

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        app.UseDefaultAllowAllCors();

        app.UseStaticFiles();

        app.UseRouting();

        app.UseIdentityServer();

        app.UseAuthorization();


        app.UseStatusCodePages(async context =>

        {
            var response = context.HttpContext.Response;

            if (response.StatusCode == StatusCodes.Status401Unauthorized ||
                response.StatusCode == StatusCodes.Status403Forbidden)
                response.Redirect("/identity/account/login");

            if (context.HttpContext.Request.Method == "Get" && response.StatusCode == StatusCodes.Status404NotFound)
            {
                response.Redirect("/index");
            }
        });

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
            endpoints.MapRazorPages();
        });
    }

1
在使用IS4时,我最终通过在services.AddAuthentication之前添加这行代码解决了问题,参考this github issue
services.ConfigureApplicationCookie(x =>
{
       x.ExpireTimeSpan = TimeSpan.FromDays(1);
});

0

我按照Github aspnetcore源代码中的AuthSamples.Cookies示例进行了跟踪。

    public void ConfigureServices(IServiceCollection services)
    {

...

        // Example of how to customize a particular instance of cookie options and
        // is able to also use other services.
        services.AddSingleton<IConfigureOptions<CookieAuthenticationOptions>, ConfigureMyCookie>();
    }

internal class ConfigureMyCookie : IConfigureNamedOptions<CookieAuthenticationOptions>
{
    // You can inject services here
    public ConfigureMyCookie()
    {
    }

    public void Configure(string name, CookieAuthenticationOptions options)
    {
        // Identityserver comes with two cookies:

        // Identity.Application
        // Identity.External

        // you can change the options here
        {
            options.ExpireTimeSpan = TimeSpan.FromHours(8);
        }
    }

    public void Configure(CookieAuthenticationOptions options)
        => Configure(Options.DefaultName, options);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接