整天都在这个问题上摸不着头脑。我正在尝试在MVC Identity 2.0.1中设置“非常长”的登录会话。 (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现在仅作为“会话”重新发布(仍然是正确的cookie名称)! 30天的到期时间已经过去了。
如果我现在关闭浏览器/再次重新打开,我将不再登录。
我已经测试过删除“提供商”并且所有工作都按预期进行,我可以在几个小时后回来并且我仍然可以正常登录。 我读到最好使用印章重新验证,所以我不确定如何继续。
答案 0 :(得分:36)
当SecurityStampValidator
触发regenerateIdentity
回调时,当前经过身份验证的用户将使用非持久性登录重新登录。这是硬编码的,我不相信有任何方法可以直接控制它。因此,登录会话将仅在您重新生成身份时运行的浏览器会话结束时继续。
这是一种使登录持久化的方法,即使在身份再生操作中也是如此。此描述基于使用Visual Studio MVC ASP.NET Web项目模板。
首先,我们需要有一种方法来跟踪登录会话在不同的HTTP请求中是否持久的事实。这可以通过添加&#34; IsPersistent&#34;声称用户的身份。以下扩展方法显示了执行此操作的方法。
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);
}
}
}
接下来我们需要制作&#34; IsPersistent&#34;当用户登录请求持久会话时声明。例如,您的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
的所有来电者现在都需要传递isPersistent
标志。例如,GenerateUserIdentityAsync
中对AccountController.SignInAsync
的调用将从
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent },
await user.GenerateUserIdentityAsync(UserManager));
到
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent },
await user.GenerateUserIdentityAsync(UserManager, isPersistent));
最后,CookieAuthenticationProvider.OnValidateIdentity
方法中使用的Startup.ConfigureAuth
委托需要注意保留身份重新生成操作中的持久性详细信息。默认委托如下所示:
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();
}
}
答案 1 :(得分:4)
ASP.NET Identity 2.2中修复了此错误。见https://aspnetidentity.codeplex.com/workitem/2319