共用方式為


ASP.NET 4.7.2 C# MVC 的 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 cookieSite none.
// Note this will also require you to be running on HTTPS
sameSiteCookie.Value = "sample";

// Set the secure flag, which Chrome's changes will require for Same
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 討論問題 中告訴我們。

會話狀態的預設 sameSite 屬性是在 會話設定的 'cookieSameSite' 參數中設定 web.config

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

MVC 驗證

OWIN MVC Cookie 型驗證會使用 Cookie 管理員來啟用 Cookie 屬性的變更。 SameSiteCookieManager.cs是這類類別的實作,您可以複製到自己的專案中。

您必須確定您的 Microsoft.Owin 元件都已升級至 4.1.0 版或更新版本。 請檢查您的 packages.config 檔案,以確保所有版本號碼都相符,例如。

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <!-- other packages -->
  <package id="Microsoft.Owin.Host.SystemWeb" version="4.1.0" targetFramework="net472" />
  <package id="Microsoft.Owin.Security" version="4.1.0" targetFramework="net472" />
  <package id="Microsoft.Owin.Security.Cookies" version="4.1.0" targetFramework="net472" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net472" />
  <package id="Owin" version="1.0" targetFramework="net472" />
</packages>

然後,驗證元件必須設定為在啟動類別中使用 CookieManager;

public void Configuration(IAppBuilder app)
{
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        CookieSameSite = SameSiteMode.None,
        CookieHttpOnly = true,
        CookieSecure = CookieSecureOption.Always,
        CookieManager = new SameSiteCookieManager(new SystemWebCookieManager())
    });
}

每個支援 Cookie 的元件都必須 設定 Cookie 管理員,這包括 CookieAuthentication 和 OpenIdConnectAuthentication。

SystemWebCookieManager 可用來避免回應 Cookie 整合的 已知問題

執行範例

如果您執行範例專案會在初始頁面上載入瀏覽器偵錯工具,並用它來檢視網站的 Cookie 集合。 若要在 Edge 和 Chrome 中這麼做,請按 F12Application 索引標籤,然後按一下區段中選項 Storage 底下的 Cookies 網站 URL。

瀏覽器偵錯工具 Cookie 清單

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

攔截您不控制的 Cookie

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

如需連結事件和SameSiteCookieRewriter.cs的範例,請參閱global.asax,以取得處理事件的範例,以及調整您可以複製到您自己的程式碼的 Cookie sameSite 屬性。

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 更新

OWIN SameSite 檔

ASP.NET 文件

.NET SameSite 修補程式