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/私密. cshtml页面或Views/Home/私密视图提供了一个页面,用于详细描述您的站点的隐私策略。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:

  • 将添加 using Microsoft.AspNetCore.Http 到 using 指令列表。Add using Microsoft.AspNetCore.Http to the list of using directives.

  • CookiePolicyOptions添加 Startup.ConfigureServicesUseCookiePolicy ,并将其添加到 Startup.ConfigureAdd CookiePolicyOptions to 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*文件添加到项目: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>
    }
    
  • 选择本文的 ASP.NET Core 2.2 版本,了解 cookie 许可功能。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.
  • " Identity 管理" 页提供了一个链接,用于下载和删除用户数据。The Identity manage page provides a link to download and delete user data.

示例应用允许你测试添加到 ASP.NET Core 2.1 模板的大多数 GDPR 扩展点和 api。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 GDPR 支持ASP.NET Core GDPR support in template-generated code

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

  • CookiePolicyOptionsUseCookiePolicy是在类中设置的 StartupCookiePolicyOptions and UseCookiePolicy are set in the Startup class.
  • * _ CookieConsentPartial* 分部视图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/私密. cshtml页面或Views/Home/私密视图提供了一个页面,用于详细描述您的站点的隐私策略。The Pages/Privacy.cshtml page or Views/Home/Privacy.cshtml view provides a page to detail your site's privacy policy. * _ CookieConsentPartial*文件生成指向隐私页面的链接。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.ConfigureServicesCookiePolicyOptions 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.ConfigureUseCookiePolicy 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 分部视图_CookieConsentPartial.cshtml partial view

* _ CookieConsentPartial*分部视图: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 许可面板将固定在由* _ 布局 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.ConfigureServicesTo 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 代码,请参阅 Identity 基架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. 有关详细信息,请参阅向添加、下载和删除自定义用户 Identity 数据For more information, see Add, download, and delete custom user data to Identity.
  • 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