共用方式為


ASP.NET 4.7.2 C# WebForms 的 SameSite Cookie 範例

.NET Framework 4.7 內建了對 SameSite 屬性的支援,但遵循的是原始標準。 修補後的行為改變了 SameSite.None 的含義,發出值為 None 的屬性,而不是完全不發出該值。 如果您不想發出該值,可以將 Cookie 上的 SameSite 屬性設為 -1。

撰寫 SameSite 屬性

以下是如何在 Cookie 上寫入 SameSite 屬性的範例;

// Create the cookie
HttpCookie sameSiteCookie = new HttpCookie("SameSiteSample");

// Set a value for the cookie
sameSiteCookie.Value = "sample";

// Set the secure flag, which Chrome's changes will require for SameSite none.
// Note this will also require you to be running on HTTPS
sameSiteCookie.Secure = true;

// Set the cookie to HTTP only which is good practice unless you really do need
// to access it client side in scripts.
sameSiteCookie.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 -1.
sameSiteCookie.SameSite = SameSiteMode.None;

// Add the cookie to the response cookie collection
Response.Cookies.Add(sameSiteCookie);

如果您是用英語以外的語言閱讀本文,請在此 GitHub 討論問題中告知我們,您是否希望看到程式碼註解以您的母語顯示。

表單驗證 Cookie 的預設 SameSite 屬性在 web.config 中表單驗證設定的 cookieSameSite 參數中設定

<system.web>
  <authentication mode="Forms">
    <forms name=".ASPXAUTH" loginUrl="~/" cookieSameSite="None" requireSSL="true">
    </forms>
  </authentication>
</system.web>

工作階段狀態的預設 sameSite 屬性也在 web.config 的工作階段設定中由 'CookieSameSite' 參數設定

<system.web>
  <sessionState cookieSameSite="None">     
  </sessionState>
</system.web>

2019 年11 月對.NET 的更新將表單驗證和工作階段的預設設定更改為 lax,這是最相容的設定,但是如果將頁面嵌入到 iframe 中,則可能需要將此設定恢復為「無」,然後新增下面顯示的攔截程式碼,以根據瀏覽器功能調整 none 行為。

執行範例

如果您執行範例項目,則在初始頁面上載入瀏覽器偵錯工具,並使用它來查看網站的 Cookie 集合。 若要在 Edge 和 Chrome 中執行此動作,請按 F12,然後選取 Application 索引標籤,按一下 Storage 區段中 Cookies 選項底下的站台 URL。

瀏覽器偵錯工具 Cookie 清單

從上圖可以看到,當您按一下「建立 Cookies」按鈕時,範例建立的 Cookie 的 SameSite 屬性值為 Lax,與範例程式碼中設定的值相符。

攔截您無法控制的 Cookie

.NET 4.5.2 引入了一個用於攔截標頭寫入的新事件 Response.AddOnSendingHeaders。 這可用於在 Cookie 傳回用戶端機器之前進行攔截。 在範例中,我們將事件連接到靜態方法,該方法會檢查瀏覽器是否支援新的 SameSite 變更,如果不支援,則將 Cookie 更改為在設定了新 None 值時不發出該屬性。

有關連線事件的範例,請參閱 global.asax;有關處理事件和調整 Cookie sameSite 屬性的範例,請參閱 SameSiteCookieRewriter.cs

public static void FilterSameSiteNoneForIncompatibleUserAgents(object sender)
{
    HttpApplication application = sender as HttpApplication;
    if (application != null)
    {
        var userAgent = application.Context.Request.UserAgent;
        if (SameSite.BrowserDetection.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
                    }
                }
            });
        }
    }
}

您可以以大致相同的方式變更特定的命名 Cookie 行為;下面的範例在支援 None 值的瀏覽器上將預設驗證 Cookie 從 Lax 調整為 None,或在不支援 None 的瀏覽器上移除 SameSite 屬性。

public static void AdjustSpecificCookieSettings()
{
    HttpContext.Current.Response.AddOnSendingHeaders(context =>
    {
        var cookies = context.Response.Cookies;
        for (var i = 0; i < cookies.Count; i++)
        {
            var cookie = cookies[i]; 
            // Forms auth: ".ASPXAUTH"
            // Session: "ASP.NET_SessionId"
            if (string.Equals(".ASPXAUTH", cookie.Name, StringComparison.Ordinal))
            { 
                if (SameSite.BrowserDetection.DisallowsSameSiteNone(userAgent))
                {
                    cookie.SameSite = -1;
                }
                else
                {
                    cookie.SameSite = SameSiteMode.None;
                }
                cookie.Secure = true;
            }
        }
    });
}

相關資訊

Chrome 更新

ASP.NET 文件

.NET SameSite 修補程式