ASP.NET Core 3.1 Razor Pages SameSite cookie 範例

ASP.NET Core 3.0 提供對 SameSite 屬性的內建支援,包括用來隱藏寫入屬性之 UnspecifiedSameSiteMode 屬性值。

除了 IFramesOpenIdConnect 整合等進階案例之外,ASP.NET Core Identity 基本上不受 SameSite cookie 影響。

使用 Identity 時,不要 新增任何 cookie 提供者或呼叫 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)Identity 會處理此情況。

撰寫 SameSite 屬性

以下是如何在 cookie 上撰寫 SameSite 屬性的範例:

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.Unspecified.
    SameSite = SameSiteMode.None
};

// Add the cookie to the response cookie collection
Response.Cookies.Append(CookieName, "cookieValue", cookieOptions);

例如,Cookie 驗證、工作階段狀態和各種其他元件會透過 Cookie 選項設定其 sameSite 選項

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

在上述程式碼中,cookie 驗證和工作階段狀態都會將其 sameSite 屬性設定為 None,並發出具有 None 值的屬性,並將 Secure 屬性設定為 true。

執行範例

如果您執行範例專案,請在初始頁面上載入瀏覽器偵錯工具,並將其用於檢視站台的 cookie 集合。 若要在 Edge 和 Chrome 中執行此動作,請按 F12,然後選取 Application 索引標籤,按一下 Storage 區段中 Cookies 選項底下的站台 URL。

Browser Debugger Cookie List

您可以從上圖看到,當您按一下 [建立 SameSite Cookie] 按鈕時,範例所建立的 cookie 具有的 SameSite 屬性值為 Lax 且符合範例程式碼中所設定的值。

攔截 cookie

為了攔截 cookie,若要根據使用者的瀏覽器代理程式支援來調整 None 值,您必須使用 CookiePolicy 中介軟體。 這必須放入 http 要求管線中寫入 cookie 的任何元件前面,並在 ConfigureServices() 內進行設定。

若要將其插入管線中,請在 Startup.csConfigure(IApplicationBuilder, IHostingEnvironment) 方法中使用 app.UseCookiePolicy()。 例如:

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

然後在 ConfigureServices(IServiceCollection services) 中設定 cookie 原則,以在附加或刪除 cookie 時呼叫協助程式類別,如下所示:

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.Unspecified;
        }
    }
}

協助程式函式 CheckSameSite(HttpContext, CookieOptions)

  • 在將 cookie 附加至要求或從要求中將其刪除時呼叫。
  • 檢查 SameSite 屬性是否設定為 None
  • 如果 SameSite 設定為 None,且已知目前的使用者代理程式不支援 None 屬性值。 檢查是使用 SameSiteSupport 類別完成:
    • SameSite 屬性設定為 (SameSiteMode)(-1),以將其設定為不要發出值

相關資訊

Chrome 更新ASP.NET Core SameSite 文件