在 ASP.NET Core 欧洲常规数据保护法规 (GDPR) 支持EU General Data Protection Regulation (GDPR) support in ASP.NET Core

作者:Rick AndersonBy Rick Anderson

ASP.NET Core 提供 Api 和模板,以帮助满足一些欧洲常规数据保护法规 (GDPR)要求:ASP.NET Core provides APIs and templates to help meet some of the EU General Data Protection Regulation (GDPR) requirements:

  • 项目模板包含扩展点以及您可以替换为您的隐私和 cookie 的使用策略的存根的标记。The project templates include extension points and stubbed markup that you can replace with your privacy and cookie use policy.
  • Pages/Privacy.cshtml页或Views/Home/Privacy.cshtml视图提供了详细介绍站点的隐私策略的页。The Pages/Privacy.cshtml page or Views/Home/Privacy.cshtml view provides a page to detail your site's privacy policy.

若要启用默认 cookie 同意的情况下功能类似的位于 ASP.NET Core 3.0 模板生成应用程序中的 ASP.NET Core 2.2 模板:To enable the default cookie consent feature like that found in the ASP.NET Core 2.2 templates in an ASP.NET Core 3.0 template generated app:

  • 添加CookiePolicyOptionsStartup.ConfigureServicesUseCookiePolicyStartup.Configure:Add CookiePolicyOptions too Startup.ConfigureServices and UseCookiePolicy to 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();
            });
        }
    }
    
  • 添加到 cookie 同意分部 _Layout.cshtml文件:Add the cookie consent partial to the _Layout.cshtml file:

            @*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>
    
    
  • 添加 _CookieConsentPartial.cshtml文件到项目:Add the _CookieConsentPartial.cshtml file to the project:

    @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>
    }
    
  • 选择本文,了解 cookie 同意的情况下功能的 ASP.NET Core 2.2 版本。Select the ASP.NET Core 2.2 version of this article to read about the cookie consent feature.

  • 项目模板包含扩展点以及您可以替换为您的隐私和 cookie 的使用策略的存根的标记。The project templates include extension points and stubbed markup that you can replace with your privacy and cookie use policy.
  • 用于存储的个人信息中,cookie 许可功能,可要求 (和跟踪) 同意的情况下从你的用户。A cookie consent feature allows you to ask for (and track) consent from your users for storing personal information. 如果某个用户尚未同意数据收集,并且应用了CheckConsentNeeded设置为true,非必需 cookie 不会发送到浏览器。If a user hasn't consented to data collection and the app has CheckConsentNeeded set to true, non-essential cookies aren't sent to the browser.
  • Cookie 可以标记为重要。Cookies can be marked as essential. 用户尚未同意和跟踪被禁用时,甚至必不可少的 cookie 发送到浏览器。Essential cookies are sent to the browser even when the user hasn't consented and tracking is disabled.
  • TempData 和会话 cookie跟踪处于禁用状态时无法正常工作。TempData and Session cookies aren't functional when tracking is disabled.
  • 标识管理页提供了用于下载和删除用户数据的链接。The Identity manage page provides a link to download and delete user data.

示例应用允许测试大部分 GDPR 扩展点和 Api 添加到 ASP.NET Core 2.1 模板。The sample app allows you test most of the GDPR extension points and APIs added to the ASP.NET Core 2.1 templates. 请参阅自述文件测试说明的文件。See the ReadMe file for testing instructions.

查看或下载示例代码如何下载View or download sample code (how to download)

支持模板生成的代码中的 ASP.NET Core GDPRASP.NET Core GDPR support in template-generated code

Razor 页面和 MVC 使用的项目模板创建的项目包括以下 GDPR 支持:Razor Pages and MVC projects created with the project templates include the following GDPR support:

  • CookiePolicyOptionsUseCookiePolicy中设置Startup类。CookiePolicyOptions and UseCookiePolicy are set in the Startup class.
  • _CookieConsentPartial.cshtml 分部视图The _CookieConsentPartial.cshtml partial view. 接受按钮包含在此文件。An Accept button is included in this file. 当用户单击接受按钮,同意将 cookie 提供。When the user clicks the Accept button, consent to store cookies is provided.
  • Pages/Privacy.cshtml页或Views/Home/Privacy.cshtml视图提供了详细介绍站点的隐私策略的页。The Pages/Privacy.cshtml page or Views/Home/Privacy.cshtml view provides a page to detail your site's privacy policy. _CookieConsentPartial.cshtml文件可生成隐私页的链接。The _CookieConsentPartial.cshtml file generates a link to the Privacy page.
  • 对于使用单个用户帐户创建的应用程序,管理页提供链接以下载和删除个人用户数据For apps created with individual user accounts, the Manage page provides links to download and delete personal user data.

CookiePolicyOptions 和 UseCookiePolicyCookiePolicyOptions and UseCookiePolicy

CookiePolicyOptions中初始化Startup.ConfigureServices:CookiePolicyOptions are initialized in 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名为Startup.Configure:UseCookiePolicy is called in 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_CookieConsentPartial.cshtml partial view

_CookieConsentPartial.cshtml分部视图:The _CookieConsentPartial.cshtml partial view:

@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>
}

此部分中:This partial:

  • 获取用户跟踪的状态。Obtains the state of tracking for the user. 如果应用程序配置为需要同意的情况下,用户必须同意使用之前可以跟踪 cookie。If the app is configured to require consent, the user must consent before cookies can be tracked. 如果需要同意的情况下,cookie 同意面板固定的创建的导航栏的顶部 _Layout.cshtml文件。If consent is required, the cookie consent panel is fixed at top of the navigation bar created by the _Layout.cshtml file.
  • 提供了一个 HTML<p>元素以汇总您的隐私和 cookie 使用策略。Provides an HTML <p> element to summarize your privacy and cookie use policy.
  • 提供指向隐私页面或视图,其中详细介绍站点的隐私策略。Provides a link to Privacy page or view where you can detail your site's privacy policy.

基本 cookieEssential cookies

如果同意来存储 cookie 未对其提供,仅标记为重要的 cookie 会被发送到浏览器。If consent to store cookies hasn't been provided, only cookies marked essential are sent to the browser. 下面的代码使 cookie 重要:The following code makes a cookie essential:

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");
}

TempData 提供程序和会话状态的 cookie 不重要TempData provider and session state cookies aren't essential

TempData 提供程序cookie 不是必需的。The TempData provider cookie isn't essential. 如果禁用跟踪,TempData 提供程序不起作用。If tracking is disabled, the TempData provider isn't functional. 若要启用 TempData 提供程序跟踪处于禁用状态时,将 TempData cookie 标记为重要中Startup.ConfigureServices:To enable the TempData provider when tracking is disabled, mark the TempData cookie as essential in 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;
});

会话状态cookie 不重要。Session state cookies are not essential. 跟踪处于禁用状态时,会话状态不起作用。Session state isn't functional when tracking is disabled. 下面的代码使基本会话 cookie:The following code makes session cookies essential:

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

个人数据Personal data

使用个人用户帐户创建的 ASP.NET Core 应用包括要下载和删除个人数据的代码。ASP.NET Core apps created with individual user accounts include code to download and delete personal data.

选择的用户名称,然后选择个人数据:Select the user name and then select Personal data:

管理个人数据页

注意:Notes:

  • 若要生成Account/Manage代码,请参阅基架标识To generate the Account/Manage code, see Scaffold Identity.
  • 删除下载链接只作用于的默认标识数据。The Delete and Download links only act on the default identity data. 创建自定义用户数据的应用,必须进行扩展,以删除/下载自定义用户数据。Apps that create custom user data must be extended to delete/download the custom user data. 有关详细信息,请参阅添加、 下载和删除自定义用户数据到标识For more information, see Add, download, and delete custom user data to Identity.
  • 保存用户的标识数据库表中存储的令牌AspNetUserTokens时通过级联删除方式,由于删除了用户会被删除外键Saved tokens for the user that are stored in the Identity database table AspNetUserTokens are deleted when the user is deleted via the cascading delete behavior due to the foreign key.
  • 外部提供程序身份验证,如 Facebook 和 Google,不可用之前接受 cookie 策略。External provider authentication, such as Facebook and Google, isn't available before the cookie policy is accepted.

静态加密Encryption at rest

某些数据库和存储机制允许静态加密。Some databases and storage mechanisms allow for encryption at rest. 静态加密:Encryption at rest:

  • 自动对存储的数据进行加密。Encrypts stored data automatically.
  • 无需配置、 编程中或其他工作的软件的访问的数据进行加密。Encrypts without configuration, programming, or other work for the software that accesses the data.
  • 是最简单且最安全的选项。Is the easiest and safest option.
  • 允许管理密钥和加密的数据库。Allows the database to manage keys and encryption.

例如:For example:

对于未提供静态的内置加密的数据库,您可能能够使用磁盘加密来提供相同的保护。For databases that don't provide built-in encryption at rest, you may be able to use disk encryption to provide the same protection. 例如:For example:

其他资源Additional resources