共用方式為


SameSite Cookie 和適用於 .NET 的開放 Web 介面 (OWIN)

作者:Rick Anderson

SameSite是IETF 草案,旨在提供一些保護,以防止跨網站偽造(CSRF)攻擊。 SameSite 2019 草稿

  • 預設會將 Cookie 視為 SameSite=Lax
  • 指出明確判斷 SameSite=None 提示以啟用跨網站傳遞的 Cookie 應標示為 Secure

Lax 適用於大部分的應用程式 Cookie。 某些形式的驗證 (例如 OpenID Connect (OIDC) 和 WS 同盟) 預設為 POST 型重新導向。 POST 型重新導向會觸發 SameSite 瀏覽器保護,因此 SameSite 會停用這些元件。 由於要求流程的差異,大部分 的 OAuth 登入都不會受到影響。 所有其他元件預設不會設定SameSite,並使用客戶端默認行為(舊或新)。

參數 None 會導致實作先前 2016 年草稿標準 之用戶端的相容性問題(例如 iOS 12)。 請參閱本文件中的支援舊版瀏覽器

發出 Cookie 的每個 OWIN 元件都需要決定是否 SameSite 適當。

如需本文的 ASP.NET 4.x 版本,請參閱 在 ASP.NET 中使用 SameSite Cookie。

將 API 與 SameSite 搭配使用

Microsoft.OwinSameSite有自己的實作:

  • 這不直接相依於 中的 System.Web
  • SameSite 適用於套件、.NET 4.5 和更新版本可 Microsoft.Owin 設為目標的所有版本。
  • 只有 SystemWebCookieManager 元件會直接與 類別互動System.WebHttpCookie

SystemWebCookieManager 取決於 .NET 4.7.2 System.Web API 來啟用 SameSite 支援,以及要變更行為的修補程式。

使用的原因 SystemWebCookieManager 概述於 OWIN 和 System.Web 回應 Cookie 整合問題中。 SystemWebCookieManager 在上 System.Web執行 時,建議使用 。

下列程式代碼會設定 SameSiteLax

owinContext.Response.Cookies.Append("My Key", "My Value", new CookieOptions()
{
    SameSite = SameSiteMode.Lax
});

下列 API 使用 SameSite

歷程記錄和變更

Microsoft.Owin 從未支援 SameSite 2016 年草稿標準

SameSite 2019 草稿的支援僅適用於 Microsoft.Owin 4.1.0 和更新版本。 舊版沒有修補程式。

規格的 SameSite 2019 年草稿:

  • 回溯相容於 2016 草稿。 如需詳細資訊,請參閱本文件中的支援舊版瀏覽器
  • 指定預設會將 SameSite=Lax Cookie 視為 。
  • 指定明確判斷 SameSite=None 提示以啟用跨網站傳遞的 Cookie 應標示為 SecureNone 是要選擇退出的新項目。
  • 排定於 2020 年 2 月Chrome 依預設啟用。 瀏覽器於 2019 年開始移轉至此標準。
  • 由 KB 文章中所述的修補程式所支援。 如需詳細資訊,請參閱 支援 .NET Framework 中 SameSite 的 KB 文章。

支援舊版瀏覽器

2016 SameSite 年標準規定未知的值必須視為 SameSite=Strict 值。 從支援 2016 SameSite 標準之舊版瀏覽器存取的應用程式,在取得 SameSite 值為 None的屬性時可能會中斷。 如果 Web 應用程式預定要支援舊版瀏覽器,則必須實作瀏覽器偵測。 ASP.NET 不會實作瀏覽器偵測,因為User-Agents值高度變動且經常變更。 ICookieManager 中的擴充點允許插入 User-Agent 特定邏輯。

Startup.Configuration 中,新增如下的程式碼:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseOpenIdConnectAuthentication(
             new OpenIdConnectAuthenticationOptions
             {
                 // … Your preexisting options … 
                 CookieManager = new SameSiteCookieManager(
                                     new SystemWebCookieManager())
             });

        // Remaining code removed for brevity.

上述程式代碼需要 .NET 4.7.2 或更新版本的 SameSite 修補程式。

下列程式代碼示範 的範例實作 SameSiteCookieManager

public class SameSiteCookieManager : ICookieManager
{
    private readonly ICookieManager _innerManager;

    public SameSiteCookieManager() : this(new CookieManager())
    {
    }

    public SameSiteCookieManager(ICookieManager innerManager)
    {
        _innerManager = innerManager;
    }

    public void AppendResponseCookie(IOwinContext context, string key, string value,
                                     CookieOptions options)
    {
        CheckSameSite(context, options);
        _innerManager.AppendResponseCookie(context, key, value, options);
    }

    public void DeleteCookie(IOwinContext context, string key, CookieOptions options)
    {
        CheckSameSite(context, options);
        _innerManager.DeleteCookie(context, key, options);
    }

    public string GetRequestCookie(IOwinContext context, string key)
    {
        return _innerManager.GetRequestCookie(context, key);
    }

    private void CheckSameSite(IOwinContext context, CookieOptions options)
    {
        if (options.SameSite == Microsoft.Owin.SameSiteMode.None 
                             && DisallowsSameSiteNone(context))
        {
            options.SameSite = null;
        }
    }

在上述範例中, DisallowsSameSiteNone 會在 方法中 CheckSameSite 呼叫 。 DisallowsSameSiteNone 是使用者方法,可偵測使用者代理程式是否不支援 SameSite None

private void CheckSameSite(IOwinContext context, CookieOptions options)
{
    if (options.SameSite == Microsoft.Owin.SameSiteMode.None 
                         && DisallowsSameSiteNone(context))
    {
        options.SameSite = null;
    }
}

下列程式碼顯示範例 DisallowsSameSiteNone 方法:

警告

下列程式碼僅供示範之用:

  • 不應將其視為完整程式碼。
  • 該程式碼不受維護或支援。
public static bool DisallowsSameSiteNone(IOwinContext context)
{
    var userAgent = context.Request.Headers["User-Agent"];
    
    if (string.IsNullOrEmpty(userAgent))
    {
        return false;
    }
    
    // Cover all iOS based browsers here. This includes:
    // - Safari on iOS 12 for iPhone, iPod Touch, iPad
    // - WkWebview on iOS 12 for iPhone, iPod Touch, iPad
    // - Chrome on iOS 12 for iPhone, iPod Touch, iPad
    // All of which are broken by SameSite=None, because they use the iOS 
    // networking stack.
    if (userAgent.Contains("CPU iPhone OS 12") ||
        userAgent.Contains("iPad; CPU OS 12"))
    {
        return true;
    }

    // Cover Mac OS X based browsers that use the Mac OS networking stack. 
    // This includes:
    // - Safari on Mac OS X.
    // This does not include:
    // - Chrome on Mac OS X
    // Because they do not use the Mac OS networking stack.
    if (userAgent.Contains("Macintosh; Intel Mac OS X 10_14") &&
        userAgent.Contains("Version/") && userAgent.Contains("Safari"))
    {
        return true;
    }

    // Cover Chrome 50-69, because some versions are broken by SameSite=None, 
    // and none in this range require it.
    // Note: this covers some pre-Chromium Edge versions, 
    // but pre-Chromium Edge does not require SameSite=None.
    if (userAgent.Contains("Chrome/5") || userAgent.Contains("Chrome/6"))
    {
        return true;
    }

    return false;
}

測試應用程式的 SameSite 問題

與遠端站台互動的應用程式 (例如透過第三方登入者) 必須:

使用可加入加入新 SameSite 行為的用戶端版本來測試 Web 應用程式。 Chrome、Firefox 和 Chromium Edge 都有新的選擇加入功能旗標可用於測試。 您的應用程式套 SameSite 用修補程序之後,請使用舊版用戶端版本來測試修補程式,特別是Safari。 如需詳細資訊,請參閱本文件中的支援舊版瀏覽器

使用 Chrome 進行測試

Chrome 78+ 設置了暫時性緩和措施,因此會提供誤導性的結果。 Chrome 78+ 暫存風險降低允許不到兩分鐘的 Cookie。 已啟用適當測試旗標的 Chrome 76 或 77 可提供更精確的結果。 若要測試新的SameSite行為切換chrome://flags/#same-site-by-default-cookies[已啟用]。 系統回報舊版的 Chrome (75 和更低版本) 在使用新的 None 設定時會失敗。 請參閱本文件中的支援舊版瀏覽器

Google 不提供較舊的 Chrome 版本。 請依照下載 Chromium 中的指示,對舊版 Chrome 進行測試。 請不要用搜尋舊版 Chrome 所獲得的連結來下載 Chrome。

使用 Safari 進行測試

Safari 12 嚴格實作先前的草稿,並在新 None 值位於Cookie時失敗。 透過本文件的None支援舊版瀏覽器中的瀏覽器偵測程式碼,可避免 。 使用 MSAL 或您使用的任何連結庫,測試 Safari 12、Safari 13 和 WebKit 型 OS 樣式登入。 問題相依於基礎 OS 版本。 OSX Mojave (10.14) 和 iOS 12 已知有新 SameSite 行為的相容性問題。 將 OS 升級至 OSX Catalina 10.15 或 iOS 13,可修正這個問題。 目前 Safari 不針對測試新規格行為提供選擇加入旗標。

使用 Firefox 進行測試

Firefox 對新標準的支援可在版本 68+ 上測試,方法是在具有功能旗標 network.cookie.sameSite.laxByDefaultabout:config 分頁上選擇加入。 目前為止並未回報任何舊版 Firefox 的相容性問題。

使用 Edge 瀏覽器進行測試

Edge 支援舊的 SameSite 標準。 Edge 44 版與新標準間沒有任何已知的相容性問題。

使用 Edge (Chromium) 進行測試

SameSite 旗標是在頁面上設定的 edge://flags/#same-site-by-default-cookies 。 未發現 Edge Chromium 的相容性問題。

使用電子進行測試

Electron 的版本包括舊版 Chromium。 例如,Teams 所使用的電子版本是 Chromium 66,其呈現較舊的行為。 您必須使用產品所使用的電子版本執行自己的相容性測試。 請參閱下一節中的支援舊版瀏覽器

其他資源