当。。。的时候SecurityStampValidator
激发regenerateIdentity
回调,当前经过身份验证的用户重新登录非持久登录。这是硬编码的,我不相信有任何方法可以直接控制它。因此,登录会话将仅持续到您正在运行的浏览器会话结束时重新生成身份。
这是一种使登录持久化的方法,即使跨身份重新生成操作也是如此。此描述基于使用 Visual Studio MVC ASP.NET Web 项目模板。
首先,我们需要有一种方法来跟踪登录会话在单独的 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);
}
}
}
接下来,当用户登录请求持久会话时,我们需要发出“IsPersistent”声明。例如,您的ApplicationUser
类可能有一个GenerateUserIdentityAsync
方法可以更新为采用isPersistent
flag 参数如下,以便在需要时做出这样的声明:
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
in AccountController.SignInAsync
会改变自
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent },
await user.GenerateUserIdentityAsync(UserManager));
to
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();
}
}