Uso de la autenticación cookie sin Identity ASP.NET Core
Por Rick Anderson
Identity ASP.NET Core es un proveedor de autenticación completo para crear y mantener inicios de sesión. Sin embargo, se puede usar un proveedor de autenticación basado en cookie sin Identity ASP.NET Core. Para más información, vea Introducción a Identity en ASP.NET Core.
Vea o descargue el código de ejemplo (cómo descargarlo)
Con fines de demostración en la aplicación de ejemplo, la cuenta de usuario del usuario hipotético, María Rodríguez, se codifica de forma rígida en la aplicación. Use la dirección de correo electrónicomaria.rodriguez@contoso.com
y cualquier contraseña para iniciar sesión en el usuario. El usuario se autentica en el método AuthenticateUser
del archivo Pages/Account/Login.cshtml.cs
. En un ejemplo real, el usuario se autenticaría en un almacén de datos.
Agregar autenticación cookie
- Agregue los servicios de middleware de autenticación con los métodos AddAuthentication y AddCookie.
- Llame a UseAuthentication y UseAuthorization para establecer la propiedad
HttpContext.User
y ejecute el middleware de autorización para las solicitudes. Se debe llamar aUseAuthentication
yUseAuthorization
antes de a los métodosMap
, como MapRazorPages y MapDefaultControllerRoute
using Microsoft.AspNetCore.Authentication.Cookies;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie();
builder.Services.AddHttpContextAccessor();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
AuthenticationScheme pasado a AddAuthentication
establece el esquema de autenticación predeterminado para la aplicación. AuthenticationScheme
resulta útil cuando hay varias instancias de autenticación cookie y la aplicación debe autorizarse con un esquema específico. Al establecer AuthenticationScheme
en CookieAuthenticationDefaults.AuthenticationScheme se proporciona un valor "Cookies"
para el esquema. Se puede usar cualquier valor de cadena que distinga el esquema.
El esquema de autenticación de la aplicación es diferente del esquema de autenticación cookie de la aplicación. Cuando no se proporciona un esquema de autenticación cookie en AddCookie, se usa CookieAuthenticationDefaults.AuthenticationScheme
. El CookieAuthenticationDefaults.AuthenticationScheme
Origen de GitHub muestra que está establecido en "Cookies"
.
La propiedad IsEssential de cookie de la autenticación se establece en true
de manera predeterminada. Las cookies de autenticación están permitidas cuando el visitante de un sitio no ha dado su consentimiento para la recogida de datos. Para obtener más información, vea Compatibilidad con el Reglamento general de protección de datos (RGPD) en ASP.NET Core.
La clase CookieAuthenticationOptions se usa para configurar las opciones del proveedor de autenticación.
Configure CookieAuthenticationOptions en el método AddCookie:
using Microsoft.AspNetCore.Authentication.Cookies;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
options.SlidingExpiration = true;
options.AccessDeniedPath = "/Forbidden/";
});
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
Middleware de directivas Cookie
La Cookie directiva de Middleware (origen de GitHub) UseCookiePolicy habilita las funcionalidades de directiva cookie. El middleware se procesa en el orden en que se agrega:
app.UseCookiePolicy(cookiePolicyOptions);
Usa un elemento CookiePolicyOptions proporcionado en el middleware de directivas de Cookie para controlar las características globales del procesamiento de cookie y enlazar a los controladores de procesamiento de cookie cuando se anexan o eliminan cookies.
El valor predeterminado MinimumSameSitePolicy es SameSiteMode.Lax
para permitir la autenticación de OAuth2. Para aplicar estrictamente una directiva de mismo sitio de SameSiteMode.Strict
, establezca MinimumSameSitePolicy
. Aunque esta configuración interrumpe OAuth2 y otros esquemas de autenticación entre orígenes, eleva el nivel de seguridad cookie para otros tipos de aplicaciones que no se basan en el procesamiento de solicitudes entre orígenes.
var cookiePolicyOptions = new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.Strict,
};
La configuración de middleware de directivas Cookie para MinimumSameSitePolicy
puede afectar el valor de Cookie.SameSite
en la configuración CookieAuthenticationOptions
según la matriz siguiente.
MinimumSameSitePolicy | Cookie.SameSite | Configuración resultante Cookie.SameSite |
---|---|---|
SameSiteMode.None | SameSiteMode.None SameSiteMode.Lax SameSiteMode.Strict |
SameSiteMode.None SameSiteMode.Lax SameSiteMode.Strict |
SameSiteMode.Lax | SameSiteMode.None SameSiteMode.Lax SameSiteMode.Strict |
SameSiteMode.Lax SameSiteMode.Lax SameSiteMode.Strict |
SameSiteMode.Strict | SameSiteMode.None SameSiteMode.Lax SameSiteMode.Strict |
SameSiteMode.Strict SameSiteMode.Strict SameSiteMode.Strict |
Crear una autenticación cookie
Para crear una información de usuario que contiene cookie, construya un objeto ClaimsPrincipal. La información del usuario se serializa y almacena en cookie.
Cree un objeto ClaimsIdentity con los elementos Claim necesarios y llame a SignInAsync para iniciar sesión en el usuario. En la aplicación de ejemplo, Login.cshtml.cs
contiene el siguiente código:
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
ReturnUrl = returnUrl;
if (ModelState.IsValid)
{
// Use Input.Email and Input.Password to authenticate the user
// with your custom authentication logic.
//
// For demonstration purposes, the sample validates the user
// on the email address maria.rodriguez@contoso.com with
// any password that passes model validation.
var user = await AuthenticateUser(Input.Email, Input.Password);
if (user == null)
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Email),
new Claim("FullName", user.FullName),
new Claim(ClaimTypes.Role, "Administrator"),
};
var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
//AllowRefresh = <bool>,
// Refreshing the authentication session should be allowed.
//ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
// The time at which the authentication ticket expires. A
// value set here overrides the ExpireTimeSpan option of
// CookieAuthenticationOptions set with AddCookie.
//IsPersistent = true,
// Whether the authentication session is persisted across
// multiple requests. When used with cookies, controls
// whether the cookie's lifetime is absolute (matching the
// lifetime of the authentication ticket) or session-based.
//IssuedUtc = <DateTimeOffset>,
// The time at which the authentication ticket was issued.
//RedirectUri = <string>
// The full path or absolute URI to be used as an http
// redirect response value.
};
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
_logger.LogInformation("User {Email} logged in at {Time}.",
user.Email, DateTime.UtcNow);
return LocalRedirect(Url.GetLocalUrl(returnUrl));
}
// Something failed. Redisplay the form.
return Page();
}
Si quiere que los comentarios de código se traduzcan en más idiomas además del inglés, háganoslo saber en este problema de debate de GitHub.
SignInAsync
crea un cookie cifrado y lo agrega a la respuesta actual. Si AuthenticationScheme
no se especifica, se usa el esquema predeterminado.
RedirectUri solo se usa en algunas rutas de acceso específicas de manera predeterminada, por ejemplo, la ruta de acceso de inicio de sesión y las rutas de cierre de sesión. Para obtener más información, consulta el origen CookieAuthenticationHandler.
Se usa el sistema de protección de datos de ASP.NET Core para el cifrado. En el caso de una aplicación hospedada en varias máquinas, el equilibrio de carga entre aplicaciones o el uso de una granja de servidores web, configure la protección de datos para usar el mismo anillo de claves y el mismo identificador de aplicación.
Cerrar sesión
Para cerrar la sesión del usuario actual y eliminar su cookie, llame a SignOutAsync:
public async Task OnGetAsync(string returnUrl = null)
{
if (!string.IsNullOrEmpty(ErrorMessage))
{
ModelState.AddModelError(string.Empty, ErrorMessage);
}
// Clear the existing external cookie
await HttpContext.SignOutAsync(
CookieAuthenticationDefaults.AuthenticationScheme);
ReturnUrl = returnUrl;
}
Si CookieAuthenticationDefaults.AuthenticationScheme
o "Cookies" no se usan como esquema, proporciona el esquema usado al configurar el proveedor de autenticación. De lo contrario, se usa el esquema predeterminado. Por ejemplo, si se utiliza "ContosoCookie" como esquema, proporciona el esquema utilizado al configurar el proveedor de autenticación.
Cuando el explorador se cierra, elimina automáticamente las cookies de sesión (cookies no persistentes), pero no se eliminan las cookies cuando se cierra una pestaña individual. El servidor no recibe notificaciones de eventos de cierre de pestaña o explorador.
Reaccionar a los cambios de back-end
Una vez creada una cookie, la cookie es el único origen de identity. Si una cuenta de usuario está deshabilitada en sistemas back-end:
- El sistema de autenticación cookie de la aplicación continúa procesando solicitudes basadas en la autenticación cookie.
- El usuario permanece conectado a la aplicación siempre que la autenticación cookie sea válida.
El evento ValidatePrincipal se puede usar para interceptar e invalidar la validación de cookieidentity. Validar cookie en cada solicitud mitiga el riesgo de que los usuarios revocados accedan a la aplicación.
Un enfoque para la validación cookie se basa en realizar un seguimiento de cuándo cambia la base de datos de usuario. Si no se ha cambiado la base de datos desde que se emitió el cookie del usuario, no es necesario volver a autenticar al usuario si su cookie sigue siendo válido. En la aplicación de ejemplo, la base de datos se implementa en IUserRepository
y almacena un valor LastChanged
. Cuando un usuario se actualiza en la base de datos, el valor LastChanged
se establece en la hora actual.
Para invalidar cookie cuando la base de datos cambia en función del valor LastChanged
, cree cookie con una notificación LastChanged
que contenga el valor actual LastChanged
de la base de datos:
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Email),
new Claim("LastChanged", {Database Value})
};
var claimsIdentity = new ClaimsIdentity(
claims,
CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity));
Para implementar una invalidación para el evento ValidatePrincipal
, escriba un método con la siguiente firma en una clase que derive de CookieAuthenticationEvents:
ValidatePrincipal(CookieValidatePrincipalContext)
A continuación se muestra una implementación de ejemplo de CookieAuthenticationEvents
:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
{
private readonly IUserRepository _userRepository;
public CustomCookieAuthenticationEvents(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public override async Task ValidatePrincipal(CookieValidatePrincipalContext context)
{
var userPrincipal = context.Principal;
// Look for the LastChanged claim.
var lastChanged = (from c in userPrincipal.Claims
where c.Type == "LastChanged"
select c.Value).FirstOrDefault();
if (string.IsNullOrEmpty(lastChanged) ||
!_userRepository.ValidateLastChanged(lastChanged))
{
context.RejectPrincipal();
await context.HttpContext.SignOutAsync(
CookieAuthenticationDefaults.AuthenticationScheme);
}
}
}
Registre la instancia de eventos durante el registro del servicio cookie. Proporcione un registro de servicio con ámbito para la clase CustomCookieAuthenticationEvents
:
using Microsoft.AspNetCore.Authentication.Cookies;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.EventsType = typeof(CustomCookieAuthenticationEvents);
});
builder.Services.AddScoped<CustomCookieAuthenticationEvents>();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapDefaultControllerRoute();
app.Run();
Considere una situación en la que se actualiza el nombre del usuario, una decisión que no afecta a la seguridad de ninguna manera. Si desea actualizar de forma no destructiva la entidad de seguridad de usuario, llame a context.ReplacePrincipal
y establezca la propiedad context.ShouldRenew
en true
.
Advertencia
El enfoque descrito aquí se desencadena en cada solicitud. Validar las cookies de autenticación de todos los usuarios en cada solicitud puede suponer una gran penalización de rendimiento para la aplicación.
Cookies persistentes
Es posible que desee que cookie persista en las sesiones del explorador. Esta persistencia solo debe habilitarse con el consentimiento explícito del usuario con una casilla "Recordarme" al iniciar sesión o un mecanismo similar.
El siguiente fragmento de código crea una identity y la cookie correspondiente que sobrevive a través de cierres del explorador. Se respetan las opciones de expiración deslizante configuradas anteriormente. Si cookie expira mientras se cierra el explorador, el explorador borra cookie una vez reiniciado.
Establezca IsPersistent en true
en AuthenticationProperties:
// using Microsoft.AspNetCore.Authentication;
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
new AuthenticationProperties
{
IsPersistent = true
});
Expiración absoluta de cookie
Se puede establecer una hora de expiración absoluta con ExpiresUtc. Para crear un objeto persistente cookie, IsPersistent
también debe establecerse. De lo contrario, cookie se crea con una duración basada en sesión y podría expirar antes o después del vale de autenticación que contiene. Cuando ExpiresUtc
se establece, invalida el valor de la opción ExpireTimeSpan de CookieAuthenticationOptions, si se establece.
El siguiente fragmento de código crea una identity y la cookie correspondiente que dura 20 minutos. Esto omite cualquier configuración de expiración deslizante configurada anteriormente.
// using Microsoft.AspNetCore.Authentication;
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTime.UtcNow.AddMinutes(20)
});
Identity ASP.NET Core es un proveedor de autenticación completo para crear y mantener inicios de sesión. Sin embargo, se puede usar un proveedor de autenticación basado en cookie sin Identity ASP.NET Core. Para más información, vea Introducción a Identity en ASP.NET Core.
Vea o descargue el código de ejemplo (cómo descargarlo)
Con fines de demostración en la aplicación de ejemplo, la cuenta de usuario del usuario hipotético, María Rodríguez, se codifica de forma rígida en la aplicación. Use la dirección de correo electrónicomaria.rodriguez@contoso.com
y cualquier contraseña para iniciar sesión en el usuario. El usuario se autentica en el método AuthenticateUser
del archivo Pages/Account/Login.cshtml.cs
. En un ejemplo real, el usuario se autenticaría en una base de datos.
Configuración
En el método Startup.ConfigureServices
, cree los servicios de middleware de autenticación con los métodos AddAuthentication y AddCookie:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie();
AuthenticationScheme pasado a AddAuthentication
establece el esquema de autenticación predeterminado para la aplicación. AuthenticationScheme
resulta útil cuando hay varias instancias de autenticación cookie y desea autorizar con un esquema específico. Al establecer AuthenticationScheme
en CookieAuthenticationDefaults.AuthenticationScheme se proporciona un valor "Cookies" para el esquema. Puede proporcionar cualquier valor de cadena que distinga el esquema.
El esquema de autenticación de la aplicación es diferente del esquema de autenticación cookie de la aplicación. Cuando no se proporciona un esquema de autenticación de cookie en AddCookie, se usa CookieAuthenticationDefaults.AuthenticationScheme
("Cookies").
La propiedad IsEssential de cookie de la autenticación se establece en true
de manera predeterminada. Las cookies de autenticación están permitidas cuando el visitante de un sitio no ha dado su consentimiento para la recogida de datos. Para obtener más información, vea Compatibilidad con el Reglamento general de protección de datos (RGPD) en ASP.NET Core.
En Startup.Configure
, llame a UseAuthentication
y UseAuthorization
para establecer la propiedad HttpContext.User
y ejecute el middleware de autorización para las solicitudes. Llame a los métodos UseAuthentication
y UseAuthorization
antes de llamar a UseEndpoints
:
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
La clase CookieAuthenticationOptions se usa para configurar las opciones del proveedor de autenticación.
Establezca CookieAuthenticationOptions
en la configuración del servicio para la autenticación en el método Startup.ConfigureServices
:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
...
});
Middleware de directivas Cookie
El middleware de directivas Cookie habilita las funcionalidades de directiva cookie. Agregar el middleware a la canalización de procesamiento de las aplicaciones distingue el orden; solo afecta a los componentes de bajada registrados en la canalización.
app.UseCookiePolicy(cookiePolicyOptions);
Usa un elemento CookiePolicyOptions proporcionado en el middleware de directivas de Cookie para controlar las características globales del procesamiento de cookie y enlazar a los controladores de procesamiento de cookie cuando se anexan o eliminan cookies.
El valor predeterminado MinimumSameSitePolicy es SameSiteMode.Lax
para permitir la autenticación de OAuth2. Para aplicar estrictamente una directiva de mismo sitio de SameSiteMode.Strict
, establezca MinimumSameSitePolicy
. Aunque esta configuración interrumpe OAuth2 y otros esquemas de autenticación entre orígenes, eleva el nivel de seguridad cookie para otros tipos de aplicaciones que no se basan en el procesamiento de solicitudes entre orígenes.
var cookiePolicyOptions = new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.Strict,
};
La configuración de middleware de directivas Cookie para MinimumSameSitePolicy
puede afectar el valor de Cookie.SameSite
en la configuración CookieAuthenticationOptions
según la matriz siguiente.
MinimumSameSitePolicy | Cookie.SameSite | Configuración resultante Cookie.SameSite |
---|---|---|
SameSiteMode.None | SameSiteMode.None SameSiteMode.Lax SameSiteMode.Strict |
SameSiteMode.None SameSiteMode.Lax SameSiteMode.Strict |
SameSiteMode.Lax | SameSiteMode.None SameSiteMode.Lax SameSiteMode.Strict |
SameSiteMode.Lax SameSiteMode.Lax SameSiteMode.Strict |
SameSiteMode.Strict | SameSiteMode.None SameSiteMode.Lax SameSiteMode.Strict |
SameSiteMode.Strict SameSiteMode.Strict SameSiteMode.Strict |
Crear una autenticación cookie
Para crear una información de usuario que contiene cookie, construya un objeto ClaimsPrincipal. La información del usuario se serializa y almacena en cookie.
Cree un ClaimsIdentity con los Claim necesarios y llame a SignInAsync para iniciar sesión en el usuario:
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Email),
new Claim("FullName", user.FullName),
new Claim(ClaimTypes.Role, "Administrator"),
};
var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
//AllowRefresh = <bool>,
// Refreshing the authentication session should be allowed.
//ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(10),
// The time at which the authentication ticket expires. A
// value set here overrides the ExpireTimeSpan option of
// CookieAuthenticationOptions set with AddCookie.
//IsPersistent = true,
// Whether the authentication session is persisted across
// multiple requests. When used with cookies, controls
// whether the cookie's lifetime is absolute (matching the
// lifetime of the authentication ticket) or session-based.
//IssuedUtc = <DateTimeOffset>,
// The time at which the authentication ticket was issued.
//RedirectUri = <string>
// The full path or absolute URI to be used as an http
// redirect response value.
};
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
Si quiere que los comentarios de código se traduzcan en más idiomas además del inglés, háganoslo saber en este problema de debate de GitHub.
SignInAsync
crea un cookie cifrado y lo agrega a la respuesta actual. Si AuthenticationScheme
no se especifica, se usa el esquema predeterminado.
RedirectUri solo se usa en algunas rutas de acceso específicas de manera predeterminada, por ejemplo, la ruta de acceso de inicio de sesión y las rutas de cierre de sesión. Para obtener más información, consulta el origen CookieAuthenticationHandler.
Se usa el sistema de protección de datos de ASP.NET Core para el cifrado. En el caso de una aplicación hospedada en varias máquinas, el equilibrio de carga entre aplicaciones o el uso de una granja de servidores web, configure la protección de datos para usar el mismo anillo de claves y el mismo identificador de aplicación.
Cerrar sesión
Para cerrar la sesión del usuario actual y eliminar su cookie, llame a SignOutAsync:
await HttpContext.SignOutAsync(
CookieAuthenticationDefaults.AuthenticationScheme);
Si CookieAuthenticationDefaults.AuthenticationScheme
(o "Cookies") no se usan como esquema (por ejemplo, "ContosoCookie"), proporciona el esquema usado al configurar el proveedor de autenticación. De lo contrario, se usa el esquema predeterminado.
Cuando el explorador se cierra, elimina automáticamente las cookies de sesión (cookies no persistentes), pero no se eliminan las cookies cuando se cierra una pestaña individual. El servidor no recibe notificaciones de eventos de cierre de pestaña o explorador.
Reaccionar a los cambios de back-end
Una vez creada una cookie, la cookie es el único origen de identity. Si una cuenta de usuario está deshabilitada en sistemas back-end:
- El sistema de autenticación cookie de la aplicación continúa procesando solicitudes basadas en la autenticación cookie.
- El usuario permanece conectado a la aplicación siempre que la autenticación cookie sea válida.
El evento ValidatePrincipal se puede usar para interceptar e invalidar la validación de cookieidentity. Validar cookie en cada solicitud mitiga el riesgo de que los usuarios revocados accedan a la aplicación.
Un enfoque para la validación cookie se basa en realizar un seguimiento de cuándo cambia la base de datos de usuario. Si no se ha cambiado la base de datos desde que se emitió el cookie del usuario, no es necesario volver a autenticar al usuario si su cookie sigue siendo válido. En la aplicación de ejemplo, la base de datos se implementa en IUserRepository
y almacena un valor LastChanged
. Cuando un usuario se actualiza en la base de datos, el valor LastChanged
se establece en la hora actual.
Para invalidar cookie cuando la base de datos cambia en función del valor LastChanged
, cree cookie con una notificación LastChanged
que contenga el valor actual LastChanged
de la base de datos:
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.Email),
new Claim("LastChanged", {Database Value})
};
var claimsIdentity = new ClaimsIdentity(
claims,
CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity));
Para implementar una invalidación para el evento ValidatePrincipal
, escriba un método con la siguiente firma en una clase que derive de CookieAuthenticationEvents:
ValidatePrincipal(CookieValidatePrincipalContext)
A continuación se muestra una implementación de ejemplo de CookieAuthenticationEvents
:
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
public class CustomCookieAuthenticationEvents : CookieAuthenticationEvents
{
private readonly IUserRepository _userRepository;
public CustomCookieAuthenticationEvents(IUserRepository userRepository)
{
// Get the database from registered DI services.
_userRepository = userRepository;
}
public override async Task ValidatePrincipal(CookieValidatePrincipalContext context)
{
var userPrincipal = context.Principal;
// Look for the LastChanged claim.
var lastChanged = (from c in userPrincipal.Claims
where c.Type == "LastChanged"
select c.Value).FirstOrDefault();
if (string.IsNullOrEmpty(lastChanged) ||
!_userRepository.ValidateLastChanged(lastChanged))
{
context.RejectPrincipal();
await context.HttpContext.SignOutAsync(
CookieAuthenticationDefaults.AuthenticationScheme);
}
}
}
Registre la instancia de eventos durante el registro del servicio cookie en el método Startup.ConfigureServices
. Proporcione un registro de servicio con ámbito para la clase CustomCookieAuthenticationEvents
:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.EventsType = typeof(CustomCookieAuthenticationEvents);
});
services.AddScoped<CustomCookieAuthenticationEvents>();
Considere una situación en la que se actualiza el nombre del usuario, una decisión que no afecta a la seguridad de ninguna manera. Si desea actualizar de forma no destructiva la entidad de seguridad de usuario, llame a context.ReplacePrincipal
y establezca la propiedad context.ShouldRenew
en true
.
Advertencia
El enfoque descrito aquí se desencadena en cada solicitud. Validar las cookies de autenticación de todos los usuarios en cada solicitud puede suponer una gran penalización de rendimiento para la aplicación.
Cookies persistentes
Es posible que desee que cookie persista en las sesiones del explorador. Esta persistencia solo debe habilitarse con el consentimiento explícito del usuario con una casilla "Recordarme" al iniciar sesión o un mecanismo similar.
El siguiente fragmento de código crea una identity y la cookie correspondiente que sobrevive a través de cierres del explorador. Se respetan las opciones de expiración deslizante configuradas anteriormente. Si cookie expira mientras se cierra el explorador, el explorador borra cookie una vez reiniciado.
Establezca IsPersistent en true
en AuthenticationProperties:
// using Microsoft.AspNetCore.Authentication;
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
new AuthenticationProperties
{
IsPersistent = true
});
Expiración absoluta de cookie
Se puede establecer una hora de expiración absoluta con ExpiresUtc. Para crear un objeto persistente cookie, IsPersistent
también debe establecerse. De lo contrario, cookie se crea con una duración basada en sesión y podría expirar antes o después del vale de autenticación que contiene. Cuando ExpiresUtc
se establece, invalida el valor de la opción ExpireTimeSpan de CookieAuthenticationOptions, si se establece.
El siguiente fragmento de código crea una identity y la cookie correspondiente que dura 20 minutos. Esto omite cualquier configuración de expiración deslizante configurada anteriormente.
// using Microsoft.AspNetCore.Authentication;
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTime.UtcNow.AddMinutes(20)
});