ASP.NET Core MVC:设置身份验证 cookie 的过期时间

45

在我的ASP.NET Core MVC应用程序中,身份验证Cookie的生存期设置为“Session”,因此它会持续到我关闭浏览器。 我使用MVC的默认身份验证方案:

app.UseIdentity();

如何延长 cookie 的生命周期?

6个回答

51
您正在使用的 ASP.NET Identity 中间件是对一些调用 UseCookieAuthentication 的封装,它将 Cookie Authentication 中间件包含在管道中。这可以在 Identity 中间件的生成器扩展的源代码 GitHub 上看到。在这种情况下,配置基础 Cookie Authentication 如何工作所需的选项被封装在 IdentityOptions 中,并在设置依赖注入时进行配置。
确实,查看我给您提供的源代码,您会看到当您调用 app.UseIdentity() 时会运行以下操作:
var options = app.ApplicationServices.GetRequiredService<IOptions<IdentityOptions>>().Value;
app.UseCookieAuthentication(options.Cookies.ExternalCookie);
app.UseCookieAuthentication(options.Cookies.TwoFactorRememberMeCookie);
app.UseCookieAuthentication(options.Cookies.TwoFactorUserIdCookie);
app.UseCookieAuthentication(options.Cookies.ApplicationCookie);
return app;

要设置IdentityOptions类,可以使用AddIdentity<TUser, TRole>方法的一个重载版本来配置选项。因此,您只需传递一个lambda表达式来配置选项即可。在这种情况下,只需访问选项类的Cookies属性,并根据需要配置ApplicationCookie。要更改时间跨度,请执行以下操作:

services.AddIdentity<ApplicationUser, IdentityRole>(options => {

    options.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromHours(1);

});

编辑:ExpireTimeSpan属性仅在调用HttpContext.Authentication.SignInAsync时,我们传入一个AuthenticationProperties实例,其中IsPersistent设置为true才会使用。

仅使用Cookie身份验证中间件进行尝试,结果发现:如果我们在不使用此选项的情况下登录,我们将获得一个持续会话时间的cookie;而如果我们同时发送此选项,则获得一个持续我们配置中间件时所需时间的cookie。

使用ASP.NET Identity的方法是将PasswordSignInAsyncisPersistent参数传递为true。这最终将调用HttpContextSignInAsync,并传入AuthenticationProperties,其中IsPersistent设置为true。调用最终类似于:

var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);

记住我(RememberMe)是配置我们是否将“IsPersistent”设置为 true 或 false 的参数。


谢谢,使用这种方法我能够改变cookie的名称,但是即使我设置了ExpireTimeSpan,auth cookie的生命周期仍然被设置为“Session”。 有任何想法吗? 这是我的Startup.cs:https://github.com/severisv/MyTeam/blob/master/src/MyTeam/Startup.cs我尝试禁用Facebook-auth。 我没有使用https。 - severin
1
@fiskeboss 我添加了一些关于这个问题的发现。 - user1620696
我正在使用Core RC1,但似乎无法正常工作。PasswordSignInAsync可以工作,但在响应中没有发送auth cookie。 - Jay Byford-Rew
“IsPersistent” 真的很有帮助 ;) - Soren
@user1620696,SignInAsync中的'async'部分很重要吗?因为我正在使用SignIn。 - ninbit
@user1620696 很抱歉在评论中这样说,但我设置了IsPersistent=false,所以当用户关闭浏览器后,下一次用户应该会注销,但是即使用户重新打开浏览器,Cookie仍然存在,用户仍然登录。有什么想法吗? - Ali Poustdouzan

29

版本2.0有一个答案,但对我没有用。我不得不这样做:

services.ConfigureApplicationCookie(options =>
{
    options.ExpireTimeSpan = TimeSpan.FromDays(30);
});

默认值为14天。


2
还是不行,它设置了cookie的过期属性,但将Expires头设置为1970年1月1日。 - Scott Wilson
已经检查过,在 .NET Core 5 中默认的过期时间为14天。响应头中的 Expires 主要用于在浏览器中缓存,因此与 cookie 无关。 - alanextar

16

在ASP.NET Core 2.0中,使用ExpireTimeSpan属性替代Cookie.Expiration。

services.ConfigureApplicationCookie(options =>
{   
    options.Cookie.Name = "CookieName";         
    options.ExpireTimeSpan = TimeSpan.FromHours(24);
    options.SlidingExpiration = true;               
});

根据文档

Cookie.Expiration: 获取或设置 cookie 的生命周期。目前,此选项不执行操作,并将在 ASP.NET Core 2.1+ 中变为过时。请使用 ExpireTimeSpan 选项设置 cookie 到期时间。


4
这已经不是真的了。以下是有关v2.1 ExpireTimeSpan 的文档摘录:在cookie中存储的身份验证票证过期的时间段。将ExpireTimeSpan添加到当前时间以创建票证的过期时间。 ExpiredTimeSpan值始终进入由服务器验证的加密AuthTicket中。它还可能进入Set-Cookie头,但仅在IsPersistent设置为true时才会如此。要将IsPersistent设置为true,请配置传递给SignInAsync的AuthenticationProperties。ExpireTimeSpan的默认值为14天。 - Igor Soloydenko

13

对于 ASP.NET Core 2.0

  services.ConfigureApplicationCookie(options =>
        {
            options.Cookie.Name = "CookieName";
            options.Cookie.Expiration = TimeSpan.FromDays(2);
        });

2
我还加入了 options.ExpireTimeSpan = TimeSpan.FromDays(2); - 即使微软改变了做法,其中一个也是正确的。 - gbjbaanb
options.ExpireTimeSpan 是存储在 cookie 中的应用程序值(并受到保护),浏览器或攻击者无法访问;而 options.Cookie.Expiration 是将向浏览器传达的时间跨度。通常需要对两个时间戳进行对齐,以避免意外过期。 - timmi4sa
@timmi4sa:这并不简单。在较新版本的 .Net Core 上,options.Cookie.Expiration 实际上会触发配置异常,警告不应使用它。 - Brian

2

尝试

app.UseIdentity().UseCookieAuthentication(
    new CookieAuthenticationOptions
    {
        ExpireTimeSpan = TimeSpan.FromHours(1)
    }
);

3
我尝试过其他选项,但似乎被忽略了。 - Pieter van Kampen
1
.NET Core 3.1 中没有 UseIdentity() 应用程序。存在其现代等价物吗? - NickG

1
由于某些原因,当使用SignInAsync([..], true)时,cookie从未在浏览器中显示(可能是登录失败)。因此,我尝试将UTC时区差添加到ExpireTimeSpan的时间间隔中。
services.AddIdentity<ApplicationUser, IdentityRole>(o =>
{
    // add TimeSpan with 5 minutes plus timezone difference from Utc time
    o.Cookies.ApplicationCookie.ExpireTimeSpan = DateTime.Now.Subtract(DateTime.UtcNow).Add( TimeSpan.FromMinutes(5) );

});

看,它奏效了,在浏览器中只显示+5分钟的过期时间。

回应github.com的PingBack https://github.com/aspnet/Identity/issues/766#issuecomment-253237576


ApplicationUser和IdentityRole来自哪里? - jjxtra
我按照这里的指示进行了操作:https://learn.microsoft.com/de-de/aspnet/core/migration/identity?view=aspnetcore-2.2。其中大部分都是从IdentityUser继承而来的。 - Ole K

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