Ejemplo cookie de SameSite de MVC de ASP.NET Core 2.1
ASP.NET Core 2.1 tiene compatibilidad integrada con el atributo SameSite, pero se escribió en el estándar original. El comportamiento revisado cambió el significado de SameSite.None
para emitir el atributo sameSite con un valor de None
, en lugar de no emitir el valor en absoluto. Si no desea emitir el valor, puede establecer la propiedad SameSite
en una cookie a -1.
ASP.NET Core Identity no se ve afectado en gran medida por las cookies de SameSite excepto en escenarios avanzados como la integración de IFrames
o OpenIdConnect
.
Al usar Identity
, no agregue ningún proveedor de cookie o llame a services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
, Identity
se encarga de ello.
Escritura del atributo SameSite
A continuación se muestra un ejemplo de cómo escribir un atributo SameSite en cookie:
var cookieOptions = new CookieOptions
{
// Set the secure flag, which Chrome's changes will require for SameSite none.
// Note this will also require you to be running on HTTPS
Secure = true,
// Set the cookie to HTTP only which is good practice unless you really do need
// to access it client side in scripts.
HttpOnly = true,
// Add the SameSite attribute, this will emit the attribute with a value of none.
// To not emit the attribute at all set the SameSite property to (SameSiteMode)(-1).
SameSite = SameSiteMode.None
};
// Add the cookie to the response cookie collection
Response.Cookies.Append(CookieName, "cookieValue", cookieOptions);
Configuración de cookies de estado de sesión y autenticación Cookie.
Autenticación de Cookie, estado de sesión y otros componentes establecen sus opciones de sameSite a través de opciones de Cookie, por ejemplo
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.IsEssential = true;
});
services.AddSession(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.IsEssential = true;
});
En el código anterior, tanto la autenticación de cookie como el estado de sesión establecen su atributo de sameSite en None
, emiten el atributo con un valor None
y también establecen el atributo Secure en true.
Ejecución del ejemplo
Si ejecuta el proyecto de ejemplo, cargue el depurador del explorador en la página inicial y úselo para ver la colección de cookie del sitio. Para ello, en Edge y Chrome, presione F12
, seleccione la pestaña Application
y haga clic en la dirección URL del sitio en la opción Cookies
de la sección Storage
.
Puede ver en la imagen anterior que la cookie creada por el ejemplo al hacer clic en el botón "Crear Cookie de SameSite" tiene un valor de atributo SameSite de Lax
, que coincide con el valor establecido en el código de ejemplo.
Interceptación de cookies
Para interceptar cookies y ajustar el valor none según su compatibilidad con el agente del explorador del usuario, debes usar el middleware CookiePolicy
. Debe colocarse en la canalización de solicitudes http antes de los componentes que escriben cookies y se configuran dentro de ConfigureServices()
.
Para insertarlo en la canalización, use app.UseCookiePolicy()
en el método Configure(IApplicationBuilder, IHostingEnvironment)
de Startup.cs. Por ejemplo:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseSession();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
A continuación, en ConfigureServices(IServiceCollection services)
configura la directiva de cookie para llamar a una clase auxiliar cuando se anexan o eliminan cookies. Por ejemplo:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
}
private void CheckSameSite(HttpContext httpContext, CookieOptions options)
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (SameSite.BrowserDetection.DisallowsSameSiteNone(userAgent))
{
options.SameSite = (SameSiteMode)(-1);
}
}
}
La función auxiliar CheckSameSite(HttpContext, CookieOptions)
:
- Se llama cuando se anexan cookies a la solicitud o se eliminan de la solicitud.
- Comprueba si la propiedad
SameSite
está establecida enNone
. - Si
SameSite
se establece enNone
y se sabe que el agente de usuario actual no admite el valor de atributo none. La comprobación se realiza mediante la clase SameSiteSupport:- Establece
SameSite
para no emitir el valor estableciendo la propiedad en(SameSiteMode)(-1)
- Establece
Destino de .NET Framework
ASP.NET Core y System.Web (ASP.NET 4.x) tienen implementaciones independientes de SameSite. Las revisiones de KB de SameSite para .NET Framework no son necesarias si se usa ASP.NET Core ni se aplica el requisito de versión mínima del marco System.Web SameSite (.NET Framework 4.7.2) a ASP.NET Core.
ASP.NET Core en .NET requiere actualizar las dependencias del paquete NuGet para obtener las correcciones adecuadas.
Para obtener los cambios de ASP.NET Core para .NET Framework, asegúrese de que tiene una referencia directa a los paquetes y versiones revisados (2.1.14 o versiones posteriores de 2.1).
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.1.14" />
<PackageReference Include="Microsoft.AspNetCore.CookiePolicy" Version="2.1.14" />
Más información
Actualizaciones de Chrome UpdatesDocumentación de SameSite de ASP.NET CoreAnuncio de cambios en SameSite de ASP.NET Core 2.1