asp.net-mvc - tables - asp.net membership
ExpireTimeSpan ignorado después de regenerateIdentity/validateInterval duration en MVC Identity(2.0.1) (2)
Cuando SecurityStampValidator
activa la devolución de llamada regenerateIdentity
, el usuario autenticado actualmente vuelve a iniciar sesión con un inicio de sesión no persistente . Esto está codificado, y no creo que haya ninguna forma de controlarlo directamente. Como tal, la sesión de inicio de sesión continuará solo hasta el final de la sesión del navegador que esté ejecutando en el punto en que se regenere la identidad.
Este es un enfoque para hacer que el inicio de sesión sea persistente, incluso en las operaciones de regeneración de identidad. Esta descripción se basa en el uso de plantillas de proyecto web Visual Studio MVC ASP.NET.
Primero debemos tener una forma de rastrear el hecho de que una sesión de inicio de sesión es persistente en solicitudes HTTP separadas. Esto se puede hacer agregando un reclamo "IsPersistent" a la identidad del usuario. Los siguientes métodos de extensión muestran una manera de hacer esto.
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);
}
}
}
A continuación, debemos realizar el reclamo "IsPersistent" cuando el usuario inicia sesión solicitando una sesión persistente. Por ejemplo, su clase ApplicationUser
puede tener un método GenerateUserIdentityAsync
que puede actualizarse para tomar un parámetro de isPersistent
como sigue para hacer una reclamación cuando sea necesario:
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, bool isPersistent)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
userIdentity.SetIsPersistent(isPersistent);
return userIdentity;
}
Cualquier llamador de ApplicationUser.GenerateUserIdentityAsync
ahora tendrá que pasar el indicador isPersistent
. Por ejemplo, la llamada a GenerateUserIdentityAsync
en AccountController.SignInAsync
cambiaría de
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent },
await user.GenerateUserIdentityAsync(UserManager));
a
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent },
await user.GenerateUserIdentityAsync(UserManager, isPersistent));
Por último, el delegado CookieAuthenticationProvider.OnValidateIdentity
utilizado en el método Startup.ConfigureAuth
necesita cierta atención para preservar los detalles de persistencia en las operaciones de regeneración de identidad. El delegado predeterminado se ve así:
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(20),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
Esto se puede cambiar a:
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();
}
}
He estado rascándome la cabeza todo el día en este caso. Estoy intentando configurar sesiones de inicio de sesión "muy largas" en MVC Identity 2.0.1. (30 dias).
Yo uso el siguiente inicio de 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))
}
});
Que en general, funciona bien. La cookie se establece 30 días, por lo tanto, todo se ve bien.
Si cierro el navegador y vuelvo después de que haya transcurrido la duración de "validateInterval" (30 minutos aquí) todavía estoy registrado, sin embargo, la cookie ahora se vuelve a emitir como "sesión" solamente (aún el nombre correcto de la cookie). El vencimiento de 30 días se ha ido.
Si ahora cierro el navegador / vuelvo a abrir, ya no estaré conectado.
He probado la eliminación del "Proveedor" y todo funciona como se esperaba, puedo volver varias horas después y todavía estoy conectado. Sin embargo, leí que es una buena práctica usar la revalidación del sello, así que no estoy seguro de cómo proceder.
Este error se corrigió en ASP.NET Identity 2.2. Consulte https://aspnetidentity.codeplex.com/workitem/2319