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 puede reemplazar por la directiva de privacidad y cookie uso.
  • La Pages/Privacy.cshtml página o Views/Home/Privacy.cshtml vista proporciona una página para detallar la directiva de privacidad de su 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 reposo

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

  • 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 reposo, es posible que pueda 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 puede reemplazar por la directiva de privacidad y cookie uso.
  • 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 CheckConsentNeeded establecido trueen , los elementos no esenciales cookieno se envían al explorador.
  • Cookie se puede marcar como esencial. Los elementos esenciales cookie se envían al explorador incluso cuando el usuario no ha consentido y el seguimiento está deshabilitado.
  • TempData y Session cookie 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 .
  • The _CookieConsentPartial.cshtmlpartial view. 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 cookie.
  • La Pages/Privacy.cshtml página o Views/Home/Privacy.cshtml vista proporciona una página para detallar la directiva de privacidad de su sitio. El archivo _CookieConsentPartial.cshtml genera un vínculo a la Privacy página.
  • 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 and 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();
    }
}

_CookieConsentPartial.cshtml partial view

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 cookie de que se pueda realizar el seguimiento. 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 privacidad y cookie uso.
  • Proporciona un vínculo a la Privacy página o vista donde puede detallar la directiva de privacidad de su sitio.

Essencial cookie

Si no se ha proporcionado el consentimiento para almacenar cookie, solo cookie 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 cookie 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;
});

Los cookie 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 cookiesea 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:

Manage personal data page

Notas:

  • Para generar el Account/Manage código, consulte Scaffolding Identity.
  • Los vínculos Eliminar y Descargar solo actúan sobre los datos de identidad 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 reposo

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

  • 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 reposo, es posible que pueda 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 puede reemplazar por la directiva de privacidad y cookie uso.
  • La Pages/Privacy.cshtml página o Views/Home/Privacy.cshtml vista proporciona una página para detallar la directiva de privacidad de su 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>
    
    
  • Agregue 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 puede reemplazar por la directiva de privacidad y cookie uso.
  • La Pages/Privacy.cshtml página o Views/Home/Privacy.cshtml vista proporciona una página para detallar la directiva de privacidad de su 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 reposo

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

  • 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 reposo, es posible que pueda usar el cifrado de disco para proporcionar la misma protección. Por ejemplo:

Recursos adicionales