我一整天都在为这个问题挠头。我正在尝试在 MVC Identity 2.0.1 中设置“非常长”的登录 session 。 (30 天)。
我使用以下 cookie 启动:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
SlidingExpiration = true,
ExpireTimeSpan = System.TimeSpan.FromDays(30),
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/My/Login"),
CookieName = "MyLoginCookie",
Provider = new CookieAuthenticationProvider
{
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
总体来说,效果很好。 cookie 是在 30 天后设置的,一切看起来都很好。
如果我关闭浏览器并在“validateInterval”持续时间过去(此处为 30 分钟)后返回,我仍然登录,但是 cookie 现在仅作为“ session ”重新发布(仍然是正确的 cookie 名称)! 30 天的期限已经过去了。
如果我现在关闭浏览器/再次重新打开,我将不再登录。
我已经测试了删除“Provider”,然后一切都按预期工作,我可以在几个小时后回来,但我仍然可以正常登录。 我读到,最好的做法是使用邮票重新验证,所以我不确定如何继续。
最佳答案
当 SecurityStampValidator
触发 regenerateIdentity
回调时,当前经过身份验证的用户将使用非持久登录重新登录。这是硬编码的,我不相信有任何方法可以直接控制它。因此,登录 session 将仅持续到您正在运行的浏览器 session 结束时重新生成身份。
这是一种使登录持久化的方法,即使跨身份重新生成操作也是如此。此描述基于使用 Visual Studio MVC ASP.NET Web 项目模板。
首先,我们需要有一种方法来跟踪登录 session 在单独的 HTTP 请求中是持久的这一事实。这可以通过向用户身份添加“IsPersistent”声明来完成。以下扩展方法展示了执行此操作的方法。
public static class ClaimsIdentityExtensions
{
private const string PersistentLoginClaimType = "PersistentLogin";
public static bool GetIsPersistent(this System.Security.Claims.ClaimsIdentity identity)
{
return identity.Claims.FirstOrDefault(c => c.Type == PersistentLoginClaimType) != null;
}
public static void SetIsPersistent(this System.Security.Claims.ClaimsIdentity identity, bool isPersistent)
{
var claim = identity.Claims.FirstOrDefault(c => c.Type == PersistentLoginClaimType);
if (isPersistent)
{
if (claim == null)
{
identity.AddClaim(new System.Security.Claims.Claim(PersistentLoginClaimType, Boolean.TrueString));
}
}
else if (claim != null)
{
identity.RemoveClaim(claim);
}
}
}
接下来,当用户登录请求持久 session 时,我们需要发出“IsPersistent”声明。例如,您的 ApplicationUser
类可能有一个 GenerateUserIdentityAsync
方法,可以将其更新为采用 isPersistent
标志参数,如下所示,以便在以下情况下做出此类声明:需要:
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, bool isPersistent)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
userIdentity.SetIsPersistent(isPersistent);
return userIdentity;
}
ApplicationUser.GenerateUserIdentityAsync
的任何调用者现在都需要传入 isPercient
标志。例如,对 AccountController.SignInAsync
中的 GenerateUserIdentityAsync
的调用将更改为
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent },
await user.GenerateUserIdentityAsync(UserManager));
至
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent },
await user.GenerateUserIdentityAsync(UserManager, isPersistent));
最后,Startup.ConfigureAuth
方法中使用的 CookieAuthenticationProvider.OnValidateIdentity
委托(delegate)需要注意,以便在身份重新生成操作中保留持久性详细信息。默认委托(delegate)如下所示:
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(20),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
这可以更改为:
OnValidateIdentity = async (context) =>
{
await SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(20),
// Note that if identity is regenerated in the same HTTP request as a logoff attempt,
// the logoff attempt will have no effect and the user will remain logged in.
// See https://aspnetidentity.codeplex.com/workitem/1962
regenerateIdentity: (manager, user) =>
user.GenerateUserIdentityAsync(manager, context.Identity.GetIsPersistent())
)(context);
// If identity was regenerated by the stamp validator,
// AuthenticationResponseGrant.Properties.IsPersistent will default to false, leading
// to a non-persistent login session. If the validated identity made a claim of being
// persistent, set the IsPersistent flag to true so the application cookie won't expire
// at the end of the browser session.
var newResponseGrant = context.OwinContext.Authentication.AuthenticationResponseGrant;
if (newResponseGrant != null)
{
newResponseGrant.Properties.IsPersistent = context.Identity.GetIsPersistent();
}
}
关于asp.net-mvc - MVC Identity (2.0.1) 中的 regenerateIdentity/validateInterval 持续时间后忽略 ExpireTimeSpan,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23983726/