筆記目錄

Skip to content

在 ASP.NET 中設定 SameSite Cookies

TLDR

  • SameSite 屬性用於限制第三方 Cookie,防禦 CSRF 攻擊。
  • SameSite 共有三個值:None(所有請求發送,需搭配 Secure)、Lax(預設值,僅第一方或連結導向發送)、Strict(僅第一方發送)。
  • ASP.NET Core 可透過 CookiePolicyOptions 進行全域設定,並需處理舊版瀏覽器對 None 支援度不佳的問題。
  • ASP.NET Framework 4.7.2 以上支援 SameSite 設定,Session 狀態需額外透過 <sessionState> 設定。
  • 瀏覽器實作差異大,建議針對 User-Agent 進行相容性檢查。

SameSite Cookies 核心概念

SameSite Cookies 為 IETF 訂立的標準,旨在限制第三方 Cookie 的發送,以防禦跨網站要求偽造 (CSRF) 攻擊。

SameSite 屬性值說明

什麼情況下會遇到這個問題:當需要決定 Cookie 是否應隨跨站請求發送時。

  • None:Cookie 將在所有情況下的請求發送,現今必須搭配 Secure 屬性。
  • Lax:現今瀏覽器的預設值,僅在第一方上下文或用戶透過連結 (Link) 到原網站時發送。
  • Strict:Cookie 只會在第一方上下文的請求發送。

Lax 模式下的請求支援度

什麼情況下會遇到這個問題:當應用程式依賴 Cookie 進行登入驗證,且使用者透過外部網站連結進入時。

請求方式能否取得 Cookies
Link (<a>)O
Form GetO
Form PostX
iframeX
AJAXX
ImageX

WARNING

不論是「Same-Origin Policy」或是「SameSite Cookies」皆高度依賴瀏覽器實作,不同版本間的行為可能存在差異。

在 ASP.NET Core 設定 SameSite Cookies

全域設定與相容性處理

什麼情況下會遇到這個問題:當需要統一管理全站 Cookie 策略,並確保舊版瀏覽器不會因不支援 None 而導致功能異常。

Program.cs 中設定 CookiePolicyOptions,並透過 OnAppendCookie 攔截器處理舊版瀏覽器:

csharp
var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<CookiePolicyOptions>(options => {
    options.MinimumSameSitePolicy = SameSiteMode.Unspecified;

    options.OnAppendCookie = cookieContext =>
        CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
    options.OnDeleteCookie = cookieContext =>
        CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});

void CheckSameSite(HttpContext httpContext, CookieOptions options) {
    if (options.SameSite == SameSiteMode.None) {
        var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
        if (DisallowsSameSiteNone(userAgent)) {
            options.SameSite = SameSiteMode.Unspecified;
        }
    }
}

// ...其他程式碼...

app.UseCookiePolicy(); // 必須放在 UseAuthorization 前面

什麼情況下會遇到這個問題:當特定 Cookie 需要與全域策略不同的 SameSite 設定時。

csharp
Response.Cookies.Append("name", "value", new CookieOptions() { SameSite = SameSiteMode.Lax });

TIP

未設定 SameSiteMode 或指定為 Unspecified 時,瀏覽器將自行決定行為。

在 ASP.NET Framework 設定 SameSite Cookies

設定預設值與 Session

什麼情況下會遇到這個問題:在 Framework 4.7.2 以上環境,需設定全域 Cookie 預設行為。

Web.config 中設定:

xml
<configuration>
  <system.web>
    <!-- 若個別 Cookie 未設定,則以此為準 -->
    <httpCookies sameSite="Lax"></httpCookies>
    <!-- Session 需額外設定 -->
    <sessionState cookieSameSite="Lax"></sessionState>
  </system.web>
</configuration>

舊瀏覽器相容性處理

什麼情況下會遇到這個問題:在 Framework 環境中,需針對不支援 None 的舊瀏覽器進行動態修正。

Global.asax.cs 中攔截回應標頭:

csharp
protected void Application_BeginRequest(object sender, EventArgs e) {
    HttpApplication application = sender as HttpApplication;
    if (application != null) {
        var userAgent = application.Context.Request.UserAgent;
        if (DisallowsSameSiteNone(userAgent)) {
            HttpContext.Current.Response.AddOnSendingHeaders(context => {
                var cookies = context.Response.Cookies;
                for (var i = 0; i < cookies.Count; i++) {
                    var cookie = cookies[i];
                    if (cookie.SameSite == SameSiteMode.None) {
                        cookie.SameSite = (SameSiteMode)(-1); // Unspecified
                    }
                }
            });
        }
    }
}

WARNING

測試 ASP.NET_SessionId 的 Same-Site 行為時,建議使用無痕模式,以避免受先前瀏覽紀錄影響。

異動歷程

  • 2022-10-26 初版文件建立。