Compatibilidad con el Reglamento general de protección de datos (RGPD) de la UE en ASP.NET Core

Por Rick Anderson

ASP.NET Core proporciona API y plantillas para cumplir algunos de los requisitos del Reglamento general de protección de datos (RGPD) de la UE:

  • Las plantillas de proyecto incluyen puntos de extensión y marcado auxiliar que puedes reemplazar por la directiva de uso privacy y cookie.
  • La Pages/Privacy.cshtml página o Views/Home/Privacy.cshtml vista proporciona una página para detallar la privacy de privacidad de tu sitio.

Para habilitar la característica de consentimiento predeterminada cookie como la que se encuentra en las plantillas de ASP.NET Core 2.2 en una aplicación generada por la plantilla de ASP.NET Core actual, agregue el código resaltado siguiente a Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.Configure<CookiePolicyOptions>(options =>
{
    // This lambda determines whether user consent for non-essential 
    // cookies is needed for a given request.
    options.CheckConsentNeeded = context => true;

    options.MinimumSameSitePolicy = SameSiteMode.None;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

En el código anterior se usan CookiePolicyOptions y UseCookiePolicy.

  • Agregue el consentimiento parcial cookie al archivo _Layout.cshtml:

                @*Previous markup removed for brevity*@
        </header>
        <div class="container">
            <partial name="_CookieConsentPartial" />
            <main role="main" class="pb-3">
                @RenderBody()
            </main>
        </div>
    
        <footer class="border-top footer text-muted">
            <div class="container">
                &copy; 2022 - WebGDPR - <a asp-area="" asp-page="/Privacy">Privacy</a>
            </div>
        </footer>
    
        <script src="~/lib/jquery/dist/jquery.min.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
    
        @await RenderSectionAsync("Scripts", required: false)
    </body>
    </html>
    
  • Añada el archivo _CookieConsentPartial.cshtml al proyecto :

    @using Microsoft.AspNetCore.Http.Features
    
    @{
        var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
        var showBanner = !consentFeature?.CanTrack ?? false;
        var cookieString = consentFeature?.CreateConsentCookie();
    }
    
    @if (showBanner)
    {
        <div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
            Use this space to summarize your privacy and cookie use policy. <a asp-page="/Privacy">Learn More</a>.
            <button type="button" class="accept-policy close" data-bs-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
                <span aria-hidden="true">Accept</span>
            </button>
        </div>
        <script>
            (function () {
                var button = document.querySelector("#cookieConsent button[data-cookie-string]");
                button.addEventListener("click", function (event) {
                    document.cookie = button.dataset.cookieString;
                }, false);
            })();
        </script>
    }
    
  • Seleccione la versión ASP.NET Core 2.2 de este artículo para leer sobre la cookie característica de consentimiento.

Especifique el valor utilizado para realizar el seguimiento si el usuario ha consentido la cookie directiva de uso mediante la propiedad CookiePolicyOptions.ConsentCookieValue:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.Configure<CookiePolicyOptions>(options =>
{
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
    options.ConsentCookieValue = "true";
});

var app = builder.Build();

Cifrado en rest

Algunas bases de datos y mecanismos de almacenamiento permiten el cifrado en rest. Cifrado en rest:

  • Cifra automáticamente los datos almacenados.
  • Cifra sin configuración, programación u otro trabajo para el software que accede a los datos.
  • Es la opción más fácil y segura.
  • Permite a la base de datos administrar claves y cifrado.

Por ejemplo:

En el caso de las bases de datos que no proporcionan cifrado integrado en rest, es posible que puedas usar el cifrado de disco para proporcionar la misma protección. Por ejemplo:

Recursos adicionales

  • Las plantillas de proyecto incluyen puntos de extensión y marcado auxiliar que puedes reemplazar por la directiva de uso privacy y cookie.
  • Una cookie característica de consentimiento le permite solicitar (y realizar un seguimiento) del consentimiento de los usuarios para almacenar información personal. Si un usuario no ha consentido la recopilación de datos y la aplicación se ha establecido CheckConsentNeeded en true, las cookies no esenciales no se envían al explorador.
  • Las cookies se pueden marcar como esenciales. Las cookies esenciales se envían al explorador incluso cuando el usuario no ha consentido y el seguimiento está deshabilitado.
  • TempData y Session cookies no son funcionales cuando el seguimiento está deshabilitado.
  • La Identity página administrar proporciona un vínculo para descargar y eliminar datos de usuario.

Con las aplicaciones de muestra se muestra cómo usar y probar la mayor parte de las API y los puntos de extensión del RGPD que se han agregado a las plantillas de ASP.NET Core 2.1. Consulte el archivo Léame para obtener instrucciones de prueba.

Vea o descargue el código de ejemplo (cómo descargarlo)

ASP.NET Core compatibilidad con RGPD en código generado por plantillas

Razor Las páginas y los proyectos de MVC creados con las plantillas de proyecto incluyen la siguiente compatibilidad con el RGPD:

  • CookiePolicyOptions y UseCookiePolicy se establecen en la Startup clase .
  • La vista parcialdel _CookieConsentPartial.cshtml. En este archivo se incluye un botón Aceptar. Cuando el usuario hace clic en el botón Aceptar, se proporciona el consentimiento para almacenar cookies.
  • La Pages/Privacy.cshtml página o Views/Home/Privacy.cshtml vista proporciona una página para detallar la privacy de privacidad de tu sitio. El archivo _CookieConsentPartial.cshtml genera un vínculo a la página Privacy.
  • En el caso de las aplicaciones creadas con cuentas de usuario individuales, la página Administrar proporciona vínculos para descargar y eliminar datos de usuario personales.

CookiePolicyOptions y UseCookiePolicy

CookiePolicyOptions son inicializados en Startup.ConfigureServices:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services 
    // to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies 
            // is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>()
            .AddEntityFrameworkStores<ApplicationDbContext>();

        // If the app uses session state, call AddSession.
        // services.AddSession();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // This method gets called by the runtime. Use this method to configure the 
    // HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();

        app.UseAuthentication();

        // If the app uses session state, call Session Middleware after Cookie 
        // Policy Middleware and before MVC Middleware.
        // app.UseSession();

        app.UseMvc();
    }
}

UseCookiePolicy es llamado por Startup.Configure:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services 
    // to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            // This lambda determines whether user consent for non-essential cookies 
            // is needed for a given request.
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>()
            .AddEntityFrameworkStores<ApplicationDbContext>();

        // If the app uses session state, call AddSession.
        // services.AddSession();

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // This method gets called by the runtime. Use this method to configure the 
    // HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();

        app.UseAuthentication();

        // If the app uses session state, call Session Middleware after Cookie 
        // Policy Middleware and before MVC Middleware.
        // app.UseSession();

        app.UseMvc();
    }
}

Vista parcial del _CookieConsentPartial.cshtml

La vista parcial del _CookieConsentPartial.cshtml:

@using Microsoft.AspNetCore.Http.Features

@{
    var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
    var showBanner = !consentFeature?.CanTrack ?? false;
    var cookieString = consentFeature?.CreateConsentCookie();
}

@if (showBanner)
{
    <nav id="cookieConsent" class="navbar navbar-default navbar-fixed-top" role="alert">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#cookieConsent .navbar-collapse">
                    <span class="sr-only">Toggle cookie consent banner</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <span class="navbar-brand"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span></span>
            </div>
            <div class="collapse navbar-collapse">
                <p class="navbar-text">
                    Use this space to summarize your privacy and cookie use policy.
                </p>
                <div class="navbar-right">
                    <a asp-page="/Privacy" class="btn btn-info navbar-btn">Learn More</a>
                    <button type="button" class="btn btn-default navbar-btn" data-cookie-string="@cookieString">Accept</button>
                </div>
            </div>
        </div>
    </nav>
    <script>
        (function () {
            document.querySelector("#cookieConsent button[data-cookie-string]").addEventListener("click", function (el) {
                document.cookie = el.target.dataset.cookieString;
                document.querySelector("#cookieConsent").classList.add("hidden");
            }, false);
        })();
    </script>
}

Esta vista parcial:

  • Obtiene el estado de seguimiento del usuario. Si la aplicación está configurada para requerir consentimiento, el usuario debe dar su consentimiento antes de que se pueda realizar el seguimiento de las cookies. Si se requiere consentimiento, el cookie panel de consentimiento se fija en la parte superior de la barra de navegación creada por el archivo _Layout.cshtml.
  • Proporciona un elemento HTML <p> para resumir la directiva de privacy y cookie uso.
  • Proporciona un vínculo a la página o vista Privacy donde puedes detallar la directiva de privacy de tu sitio.

Cookies esenciales

Si no se ha proporcionado el consentimiento para almacenar cookies, solo las cookies se envían al explorador los marcados como esenciales. El código siguiente hace que sea cookie esencial:

public IActionResult OnPostCreateEssentialAsync()
{
    HttpContext.Response.Cookies.Append(Constants.EssentialSec, 
        DateTime.Now.Second.ToString(), 
        new CookieOptions() { IsEssential = true });

    ResponseCookies = Response.Headers[HeaderNames.SetCookie].ToString();

    return RedirectToPage("./Index");
}

El proveedor tempData y el estado de las cookies de sesión no son esenciales

El proveedorcookie TempData no es esencial. Si el seguimiento está deshabilitado, el proveedor TempData no es funcional. Para habilitar el proveedor TempData cuando el seguimiento está deshabilitado, marque TempData cookie como esencial en Startup.ConfigureServices:

// The TempData provider cookie is not essential. Make it essential
// so TempData is functional when tracking is disabled.
services.Configure<CookieTempDataProviderOptions>(options => {
    options.Cookie.IsEssential = true;
});

Las cookies del estado de sesión no son esenciales. El estado de la sesión no funciona cuando el seguimiento está desactivado. El código siguiente hace que la sesión de las cookies sea esencial:

services.AddSession(options =>
{
    options.Cookie.IsEssential = true;
});

Datos personales

ASP.NET Core aplicaciones creadas con cuentas de usuario individuales incluyen código para descargar y eliminar datos personales.

Seleccione el nombre de usuario y, a continuación, seleccione Datos personales:

Página de gestión de datos personales

Notas:

  • Para generar el Account/Manage código, consulte Scaffolding Identity.
  • Los vínculos Eliminar y Descargar solo actúan sobre los datos de identity predeterminados. Las aplicaciones que crean datos de usuario personalizados deben ampliarse para eliminar o descargar los datos de usuario personalizados. Para obtener más información, vea Agregar, descargar y eliminar datos de usuario personalizados en Identity.
  • Los tokens guardados para el usuario almacenado en la Identity tabla AspNetUserTokens de base de datos se eliminan cuando el usuario se elimina a través del comportamiento de eliminación en cascada debido a la clave externa.
  • La autenticación del proveedor externo, como Facebook y Google, no está disponible antes de que se acepte la cookie directiva.

Cifrado en rest

Algunas bases de datos y mecanismos de almacenamiento permiten el cifrado en rest. Cifrado en rest:

  • Cifra automáticamente los datos almacenados.
  • Cifra sin configuración, programación u otro trabajo para el software que accede a los datos.
  • Es la opción más fácil y segura.
  • Permite a la base de datos administrar claves y cifrado.

Por ejemplo:

En el caso de las bases de datos que no proporcionan cifrado integrado en rest, es posible que puedas usar el cifrado de disco para proporcionar la misma protección. Por ejemplo:

Recursos adicionales

  • Las plantillas de proyecto incluyen puntos de extensión y marcado auxiliar que puedes reemplazar por la directiva de uso privacy y cookie.
  • La Pages/Privacy.cshtml página o Views/Home/Privacy.cshtml vista proporciona una página para detallar la privacy de privacidad de tu sitio.

Para habilitar la característica de consentimiento predeterminada cookie como la que se encuentra en las plantillas de ASP.NET Core 2.2 en una aplicación generada por la plantilla de ASP.NET Core actual:

  • Agregue using Microsoft.AspNetCore.Http a la lista de directivas que usan.

  • Agregue CookiePolicyOptions a Startup.ConfigureServices y UseCookiePolicy a Startup.Configure:

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential 
                // cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                // requires using Microsoft.AspNetCore.Http;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
    
            services.AddRazorPages();
        }
    
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }
    
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
    
            app.UseRouting();
    
            app.UseAuthorization();
    
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
    }
    
  • Agregue el consentimiento parcial cookie al archivo _Layout.cshtml:

            @*Previous markup removed for brevity*@
        </header>
        <div class="container">
            <partial name="_CookieConsentPartial" />
            <main role="main" class="pb-3">
                @RenderBody()
            </main>
        </div>
    
        <footer class="border-top footer text-muted">
            <div class="container">
                &copy; 2019 - RPCC - <a asp-area="" asp-page="/Privacy">Privacy</a>
            </div>
        </footer>
    
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
    
        @RenderSection("Scripts", required: false)
    </body>
    </html>
    
    
  • Agrega el archivo _CookieConsentPartial.cshtml al proyecto:

    @using Microsoft.AspNetCore.Http.Features
    
    @{
        var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
        var showBanner = !consentFeature?.CanTrack ?? false;
        var cookieString = consentFeature?.CreateConsentCookie();
    }
    
    @if (showBanner)
    {
        <div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
            Use this space to summarize your privacy and cookie use policy. <a asp-page="/Privacy">Learn More</a>.
            <button type="button" class="accept-policy close" data-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
                <span aria-hidden="true">Accept</span>
            </button>
        </div>
        <script>
            (function () {
                var button = document.querySelector("#cookieConsent button[data-cookie-string]");
                button.addEventListener("click", function (event) {
                    document.cookie = button.dataset.cookieString;
                }, false);
            })();
        </script>
    }
    
  • Seleccione la versión ASP.NET Core 2.2 de este artículo para leer sobre la característica de consentimiento cookie.

  • Las plantillas de proyecto incluyen puntos de extensión y marcado auxiliar que puedes reemplazar por la directiva de uso privacy y cookie.
  • La Pages/Privacy.cshtml página o Views/Home/Privacy.cshtml vista proporciona una página para detallar la privacy de privacidad de tu sitio.

Para habilitar la característica de consentimiento predeterminada cookie como la que se encuentra en las plantillas de ASP.NET Core 2.2 en una aplicación generada por la plantilla de ASP.NET Core actual, agregue el código resaltado siguiente a Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.Configure<CookiePolicyOptions>(options =>
{
    // This lambda determines whether user consent for non-essential 
    // cookies is needed for a given request.
    options.CheckConsentNeeded = context => true;

    options.MinimumSameSitePolicy = SameSiteMode.None;
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

En el código anterior se usan CookiePolicyOptions y UseCookiePolicy.

  • Agregue el consentimiento parcial cookie al archivo _Layout.cshtml:

                @*Previous markup removed for brevity*@
        </header>
        <div class="container">
            <partial name="_CookieConsentPartial" />
            <main role="main" class="pb-3">
                @RenderBody()
            </main>
        </div>
    
        <footer class="border-top footer text-muted">
            <div class="container">
                &copy; 2022 - WebGDPR - <a asp-area="" asp-page="/Privacy">Privacy</a>
            </div>
        </footer>
    
        <script src="~/lib/jquery/dist/jquery.min.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
    
        @await RenderSectionAsync("Scripts", required: false)
    </body>
    </html>
    
  • Añada el archivo _CookieConsentPartial.cshtml al proyecto :

    @using Microsoft.AspNetCore.Http.Features
    
    @{
        var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
        var showBanner = !consentFeature?.CanTrack ?? false;
        var cookieString = consentFeature?.CreateConsentCookie();
    }
    
    @if (showBanner)
    {
        <div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
            Use this space to summarize your privacy and cookie use policy. <a asp-page="/Privacy">Learn More</a>.
            <button type="button" class="accept-policy close" data-bs-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
                <span aria-hidden="true">Accept</span>
            </button>
        </div>
        <script>
            (function () {
                var button = document.querySelector("#cookieConsent button[data-cookie-string]");
                button.addEventListener("click", function (event) {
                    document.cookie = button.dataset.cookieString;
                }, false);
            })();
        </script>
    }
    
  • Seleccione la versión ASP.NET Core 2.2 de este artículo para leer sobre la cookie característica de consentimiento.

Cifrado en rest

Algunas bases de datos y mecanismos de almacenamiento permiten el cifrado en rest. Cifrado en rest:

  • Cifra automáticamente los datos almacenados.
  • Cifra sin configuración, programación u otro trabajo para el software que accede a los datos.
  • Es la opción más fácil y segura.
  • Permite a la base de datos administrar claves y cifrado.

Por ejemplo:

En el caso de las bases de datos que no proporcionan cifrado integrado en rest, es posible que puedas usar el cifrado de disco para proporcionar la misma protección. Por ejemplo:

Recursos adicionales