Udostępnij za pośrednictwem


Praca z plikami cookie SameSite w programie ASP.NET Core

Autor: Rick Anderson

SameSite to wersja robocza standardu IETF zaprojektowana w celu zapewnienia ochrony przed atakami fałszerzowania żądań między witrynami (CSRF). Pierwotnie opracowany w 2016 r. projekt standardu został zaktualizowany w 2019 roku. Zaktualizowany standard nie jest zgodny z poprzednim standardem, a następujące są najbardziej zauważalne różnice:

  • Pliki cookie bez nagłówka SameSite są domyślnie traktowane jako SameSite=Lax pliki cookie.
  • SameSite=None musi być używany do zezwalania na używanie między witrynami cookie .
  • Pliki cookie, które potwierdzają SameSite=None , muszą być również oznaczone jako Secure.
  • Aplikacje, które używają <iframe> , mogą napotkać problemy z plikiem sameSite=Lax cookie lub sameSite=Strict plikiem cookie, ponieważ <iframe> są traktowane jako scenariusze obejmujące wiele witryn.
  • Wartość SameSite=None nie jest dozwolona przez standard 2016 i powoduje, że niektóre implementacje traktują takie pliki cookie jak SameSite=Strict. Zobacz Obsługa starszych przeglądarek w tym dokumencie.

To SameSite=Lax ustawienie działa w przypadku większości plików cookie aplikacji. Niektóre formy uwierzytelniania, takie jak OpenID Connect (OIDC) i WS-Federation domyślne przekierowania oparte na post. Przekierowania oparte na metodzie POST wyzwalają ochronę przeglądarki SameSite, więc dla tych składników jest wyłączona witryna SameSite. Większość identyfikatorów logowania OAuth nie ma wpływu na różnice w sposobie przepływu żądań.

Każdy składnik ASP.NET Core, który emituje pliki cookie, musi zdecydować, czy jest odpowiednia witryna SameSite.

SameSite i Identity

ASP.NET Core Identity nie ma wpływu na pliki cookie SameSite, z wyjątkiem zaawansowanych scenariuszy, takich jak IFrames lub OpenIdConnect integracji.

W przypadku korzystania z programu Identitynie należy dodawać żadnych cookie dostawców ani dzwonić services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)do usługi , Identity dba o to.

Przykładowy kod testowy witryny SameSite

Można pobrać i przetestować następujący przykład:

Przykład Dokument
.NET Core Razor Pages przykład ASP.NET Core 3.1 Razor Pages SameSite cookie

Obsługa platformy .NET Core dla tego samego atrybutu Lokacja

Platforma .NET Core obsługuje wersję roboczą standardu 2019 dla witryny SameSite. Deweloperzy mogą programowo kontrolować wartość tego samego atrybutu Lokacja HttpCookie.SameSite przy użyciu właściwości . SameSite Ustawienie właściwości na Strict, Laxlub None powoduje zapisanie tych wartości w sieci za pomocą elementu cookie. Ustawienie , aby wskazać, że nie należy wysyłać SameSiteMode.Unspecified żadnej lokacji z parametrem cookie.

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

        // The client should follow its default cookie policy.
        // SameSite = SameSiteMode.Unspecified
    };

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

Użycie interfejsu API w usłudze SameSite

Wartości domyślne HttpContext.Response.Cookies.Append mają wartość Unspecified, co oznacza, że do elementu nie dodano atrybutu cookie SameSite, a klient będzie używać jego domyślnego zachowania (Lax dla nowych przeglądarek, Brak dla starych). Poniższy kod pokazuje, jak zmienić cookie wartość SameSite na SameSiteMode.Lax:

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

Wszystkie składniki ASP.NET Core, które emitują pliki cookie, zastępują poprzednie wartości domyślne ustawieniami odpowiednimi dla ich scenariuszy. Przesłonięć powyższe wartości domyślne nie zostały zmienione.

Składnik cookie Wartość domyślna
CookieBuilder SameSite Unspecified
Session SessionOptions.Cookie Lax
CookieTempDataProvider CookieTempDataProviderOptions.Cookie Lax
IAntiforgery AntiforgeryOptions.Cookie Strict
Cookie Uwierzytelnianie CookieAuthenticationOptions.Cookie Lax
AddTwitter TwitterOptions.StateCookie Lax
RemoteAuthenticationHandler<TOptions> RemoteAuthenticationOptions.CorrelationCookie None
AddOpenIdConnect OpenIdConnectOptions.NonceCookie None
HttpContext.Response.Cookies.Append CookieOptions Unspecified

program ASP.NET Core 3.1 lub nowszy zapewnia następującą obsługę witryny SameSite:

  • Ponowne definiowanie zachowania emisji SameSiteMode.NoneSameSite=None
  • Dodaje nową wartość SameSiteMode.Unspecified , aby pominąć atrybut SameSite.
  • Domyślnie wszystkie interfejsy API plików cookie mają wartość Unspecified. Niektóre składniki korzystające z plików cookie ustawiają wartości bardziej specyficzne dla ich scenariuszy. Zapoznaj się z powyższą tabelą, aby zapoznać się z przykładami.

W systemie ASP.NET Core 3.0 i nowszych wartości domyślne SameSite zostały zmienione, aby uniknąć konfliktu z niespójnymi ustawieniami domyślnymi klienta. Następujące interfejsy API zmieniły wartość domyślną z SameSiteMode.Lax , aby -1 uniknąć emitowania atrybutu SameSite dla tych plików cookie:

Historia i zmiany

Obsługa sameSite została po raz pierwszy zaimplementowana w programie ASP.NET Core w wersji 2.0 przy użyciu standardu roboczego 2016. Standard 2016 był opt-in. ASP.NET Core , domyślnie ustawiając kilka plików cookie Lax . Po wystąpieniu kilku problemów z uwierzytelnianiem większość użycia witryny SameSite została wyłączona.

Poprawki zostały wydane w listopadzie 2019 r. w celu zaktualizowania standardu z 2016 r. do standardu 2019. Wersja robocza z 2019 r. specyfikacji SameSite:

  • Nie jest do tyłu zgodny z wersją roboczą z 2016 roku. Aby uzyskać więcej informacji, zobacz Obsługa starszych przeglądarek w tym dokumencie.
  • Określa, że pliki cookie są domyślnie traktowane jako SameSite=Lax .
  • Określa pliki cookie, które jawnie asertywne SameSite=None w celu włączenia dostarczania między witrynami powinny być oznaczone jako Secure. None jest nowym wpisem, aby zrezygnować.
  • Jest obsługiwany przez poprawki wydane dla ASP.NET Core 2.1, 2.2 i 3.0. program ASP.NET Core 3.1 lub nowszy ma dodatkową obsługę witryny SameSite.
  • Program Chrome ma być domyślnie włączony w lutym 2020 roku. Przeglądarki zaczęły przechodzić do tego standardu w 2019 roku.

Interfejsy API, których dotyczy zmiana z wersji roboczej SameSite z 2016 r. do wersji roboczej standardu z 2019 r.

Obsługa starszych przeglądarek

Standard SameSite z 2016 r. nakazuje traktowanie nieznanych wartości jako SameSite=Strict wartości. Aplikacje dostępne ze starszych przeglądarek, które obsługują standard SameSite 2016, mogą ulec awarii, gdy otrzymają właściwość SameSite o wartości None. Aplikacje internetowe muszą implementować wykrywanie przeglądarki, jeśli zamierzają obsługiwać starsze przeglądarki. ASP.NET Core nie implementuje wykrywania przeglądarki, ponieważ wartości agentów użytkowników są bardzo niestabilne i często zmieniają się. Punkt rozszerzenia umożliwia Microsoft.AspNetCore.CookiePolicy podłączanie logiki specyficznej dla agenta użytkownika.

W Program.cspliku dodaj kod wywołujący UseCookiePolicy przed wywołaniem UseAuthentication metody lub dowolną metodę zapisującą pliki cookie:

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 (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
        {
            options.SameSite = SameSiteMode.Unspecified;
        }
    }
}

    builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseCookiePolicy();
app.UseAuthorization();

app.MapRazorPages();

app.Run();

W Program.cspliku dodaj kod podobny do następującego wyróżnionego kodu:

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 (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
        {
            options.SameSite = SameSiteMode.Unspecified;
        }
    }
}

    builder.Services.AddRazorPages();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseCookiePolicy();
app.UseAuthorization();

app.MapRazorPages();

app.Run();

W poprzednim przykładzie jest to biblioteka dostarczana przez użytkownika, która wykrywa, MyUserAgentDetectionLib.DisallowsSameSiteNone czy agent użytkownika nie obsługuje aplikacji SameSite None:

if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
    options.SameSite = SameSiteMode.Unspecified;
}

Poniższy kod przedstawia przykładową DisallowsSameSiteNone metodę:

Ostrzeżenie

Poniższy kod jest przeznaczony tylko dla pokazu:

  • Nie należy go uważać za ukończone.
  • Nie jest ona obsługiwana ani obsługiwana.
public static bool DisallowsSameSiteNone(string userAgent)
{
    // Check if a null or empty string has been passed in, since this
    // will cause further interrogation of the useragent to fail.
     if (String.IsNullOrWhiteSpace(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;
}

Testowanie aplikacji pod kątem problemów z usługą SameSite

Aplikacje, które wchodzą w interakcje z witrynami zdalnymi, takimi jak za pośrednictwem logowania innej firmy, muszą:

Przetestuj aplikacje internetowe przy użyciu wersji klienta, która może wyrazić zgodę na nowe zachowanie w witrynie SameSite. Chrome, Firefox i Chromium Edge mają nowe flagi funkcji, które mogą być używane do testowania. Gdy aplikacja zastosuje poprawki SameSite, przetestuj ją ze starszymi wersjami klienta, zwłaszcza w przeglądarce Safari. Aby uzyskać więcej informacji, zobacz Obsługa starszych przeglądarek w tym dokumencie.

Testowanie za pomocą przeglądarki Chrome

Chrome 78+ daje mylące wyniki, ponieważ ma tymczasowe środki zaradcze. Tymczasowe środki zaradcze w przeglądarce Chrome 78+ pozwalają na używanie plików cookie mniej niż dwie minuty. Chrome 76 lub 77 z włączonymi odpowiednimi flagami testowymi zapewnia dokładniejsze wyniki. Aby przetestować nowe zachowanie SameSite, przełączenie chrome://flags/#same-site-by-default-cookies na włączone. Starsze wersje programu Chrome (75 i starsze) są zgłaszane jako nieudane z nowym None ustawieniem. Zobacz Obsługa starszych przeglądarek w tym dokumencie.

Firma Google nie udostępnia starszych wersji chrome. Postępuj zgodnie z instrukcjami w temacie Pobierz Chromium , aby przetestować starsze wersje przeglądarki Chrome. Nie pobieraj przeglądarki Chrome z linków udostępnianych przez wyszukiwanie starszych wersji przeglądarki Chrome.

Począwszy od wersji 80.0.3975.0Canary, tymczasowe ograniczenie ryzyka Lax+POST można wyłączyć na potrzeby testowania przy użyciu nowej flagi --enable-features=SameSiteDefaultChecksMethodRigorously , aby umożliwić testowanie witryn i usług w ostatecznym stanie końcowym funkcji, w której usunięto środki zaradcze. Aby uzyskać więcej informacji, zobacz Chromium Projects SameSite Updates

Testowanie za pomocą przeglądarki Safari

Przeglądarka Safari 12 ściśle zaimplementowała poprzednią wersję roboczą i kończy się niepowodzeniem, gdy nowa None wartość znajduje się w obiekcie cookie. None jest unikany za pośrednictwem kodu wykrywania przeglądarki Obsługa starszych przeglądarek w tym dokumencie. Przetestuj identyfikatory logowania w stylu systemu operacyjnego oparte na przeglądarce Safari 12, Safari 13 i WebKit przy użyciu bibliotek MSAL, ADAL lub dowolnej używanej biblioteki. Problem jest zależny od bazowej wersji systemu operacyjnego. OSX Mojave (10.14) i iOS 12 są znane z problemów ze zgodnością z nowym zachowaniem SameSite. Uaktualnienie systemu operacyjnego do systemu OSX Catalina (10.15) lub iOS 13 rozwiązuje problem. Przeglądarka Safari nie ma obecnie flagi zgody na testowanie nowego zachowania specyfikacji.

Testowanie za pomocą przeglądarki Firefox

Obsługa przeglądarki Firefox dla nowego standardu można przetestować w wersji 68 lub nowszej, decydując się na about:config stronę z flagą network.cookie.sameSite.laxByDefaultfunkcji . Nie odnotowano raportów dotyczących problemów ze zgodnością ze starszymi wersjami przeglądarki Firefox.

Testowanie za pomocą przeglądarki Edge

Przeglądarka Edge obsługuje stary standard SameSite. Przeglądarka Edge w wersji 44 nie ma żadnych znanych problemów ze zgodnością z nowym standardem.

Testowanie za pomocą przeglądarki Edge (Chromium)

Flagi SameSite są ustawiane na edge://flags/#same-site-by-default-cookies stronie. Nie odnaleziono żadnych problemów ze zgodnością z przeglądarką Edge Chromium.

Testowanie za pomocą polecenia Electron

Electron Wersje obejmują starsze wersje Chromium. Na przykład wersja Electron używana przez aplikację Teams to Chromium 66, która wykazuje starsze zachowanie. Musisz przeprowadzić własne testy zgodności z wersją używanego Electron produktu. Zobacz Obsługa starszych przeglądarek w poniższej sekcji.

Dodatkowe zasoby

Przykład Dokument
.NET Core Razor Pages przykład ASP.NET Core 3.1 Razor Pages SameSite cookie

Można pobrać i przetestować następujący przykład:

Przykład Dokument
.NET Core Razor Pages przykład ASP.NET Core 3.1 Razor Pages SameSite cookie

Obsługa platformy .NET Core dla tego samego atrybutu Lokacja

Program .NET Core 3.1 lub nowszy obsługuje wersję roboczą standardu 2019 dla witryny SameSite. Deweloperzy mogą programowo kontrolować wartość tego samego atrybutu Lokacja HttpCookie.SameSite przy użyciu właściwości . Ustawienie właściwości na SameSite Strict, Lax lub None powoduje zapisanie tych wartości w sieci za pomocą elementu cookie. Ustawienie wartości równej (SameSiteMode)(-1) wskazuje, że w sieci nie powinien być uwzględniony żaden atrybut sameSite cookie

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
    // SameSite = (SameSiteMode)(-1)
    SameSite = SameSiteMode.None
};

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

Platforma .NET Core 3.1 i nowsze obsługują zaktualizowane wartości SameSite i dodaje dodatkową wartość SameSiteMode.Unspecified wyliczenia do wyliczenia SameSiteMode . Ta nowa wartość wskazuje, że żadna witryna nie powinna być wysyłana za pomocą elementu cookie.

Użycie interfejsu API w usłudze SameSite

Wartości domyślne HttpContext.Response.Cookies.Append mają wartość Unspecified, co oznacza, że do elementu nie dodano atrybutu cookie SameSite, a klient będzie używać jego domyślnego zachowania (Lax dla nowych przeglądarek, Brak dla starych). Poniższy kod pokazuje, jak zmienić cookie wartość SameSite na SameSiteMode.Lax:

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

Wszystkie składniki ASP.NET Core, które emitują pliki cookie, zastępują poprzednie wartości domyślne ustawieniami odpowiednimi dla ich scenariuszy. Przesłonięć powyższe wartości domyślne nie zostały zmienione.

Składnik cookie Wartość domyślna
CookieBuilder SameSite Unspecified
Session SessionOptions.Cookie Lax
CookieTempDataProvider CookieTempDataProviderOptions.Cookie Lax
IAntiforgery AntiforgeryOptions.Cookie Strict
Cookie Uwierzytelnianie CookieAuthenticationOptions.Cookie Lax
AddTwitter TwitterOptions.StateCookie Lax
RemoteAuthenticationHandler<TOptions> RemoteAuthenticationOptions.CorrelationCookie None
AddOpenIdConnect OpenIdConnectOptions.NonceCookie None
HttpContext.Response.Cookies.Append CookieOptions Unspecified

program ASP.NET Core 3.1 lub nowszy zapewnia następującą obsługę witryny SameSite:

  • Ponowne definiowanie zachowania emisji SameSiteMode.NoneSameSite=None
  • Dodaje nową wartość SameSiteMode.Unspecified , aby pominąć atrybut SameSite.
  • Domyślnie wszystkie interfejsy API plików cookie mają wartość Unspecified. Niektóre składniki korzystające z plików cookie ustawiają wartości bardziej specyficzne dla ich scenariuszy. Zapoznaj się z powyższą tabelą, aby zapoznać się z przykładami.

W systemie ASP.NET Core 3.0 i nowszych wartości domyślne SameSite zostały zmienione, aby uniknąć konfliktu z niespójnymi ustawieniami domyślnymi klienta. Następujące interfejsy API zmieniły wartość domyślną z SameSiteMode.Lax , aby -1 uniknąć emitowania atrybutu SameSite dla tych plików cookie:

Historia i zmiany

Obsługa sameSite została po raz pierwszy zaimplementowana w programie ASP.NET Core w wersji 2.0 przy użyciu standardu roboczego 2016. Standard 2016 był opt-in. ASP.NET Core , domyślnie ustawiając kilka plików cookie Lax . Po wystąpieniu kilku problemów z uwierzytelnianiem większość użycia witryny SameSite została wyłączona.

Poprawki zostały wydane w listopadzie 2019 r. w celu zaktualizowania standardu z 2016 r. do standardu 2019. Wersja robocza z 2019 r. specyfikacji SameSite:

  • Nie jest do tyłu zgodny z wersją roboczą z 2016 roku. Aby uzyskać więcej informacji, zobacz Obsługa starszych przeglądarek w tym dokumencie.
  • Określa, że pliki cookie są domyślnie traktowane jako SameSite=Lax .
  • Określa pliki cookie, które jawnie asertywne SameSite=None w celu włączenia dostarczania między witrynami powinny być oznaczone jako Secure. None jest nowym wpisem, aby zrezygnować.
  • Jest obsługiwany przez poprawki wydane dla ASP.NET Core 2.1, 2.2 i 3.0. ASP.NET Core 3.1 ma dodatkową obsługę usługi SameSite.
  • Program Chrome ma być domyślnie włączony w lutym 2020 roku. Przeglądarki zaczęły przechodzić do tego standardu w 2019 roku.

Interfejsy API, których dotyczy zmiana z wersji roboczej SameSite z 2016 r. do wersji roboczej standardu z 2019 r.

Obsługa starszych przeglądarek

Standard SameSite z 2016 r. nakazuje traktowanie nieznanych wartości jako SameSite=Strict wartości. Aplikacje dostępne ze starszych przeglądarek, które obsługują standard SameSite 2016, mogą ulec awarii, gdy otrzymają właściwość SameSite o wartości None. Aplikacje internetowe muszą implementować wykrywanie przeglądarki, jeśli zamierzają obsługiwać starsze przeglądarki. ASP.NET Core nie implementuje wykrywania przeglądarki, ponieważ wartości agentów użytkowników są bardzo niestabilne i często zmieniają się. Punkt rozszerzenia umożliwia Microsoft.AspNetCore.CookiePolicy podłączanie logiki specyficznej dla agenta użytkownika.

W Startup.Configurepliku dodaj kod wywołujący UseCookiePolicy przed wywołaniem UseAuthentication metody lub dowolną metodę zapisującą pliki cookie:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseCookiePolicy();
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

W Startup.ConfigureServicespliku dodaj kod podobny do następującego:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
        options.OnAppendCookie = cookieContext =>
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
        options.OnDeleteCookie = cookieContext =>
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
    });

    services.AddRazorPages();
}

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

W poprzednim przykładzie jest to biblioteka dostarczana przez użytkownika, która wykrywa, MyUserAgentDetectionLib.DisallowsSameSiteNone czy agent użytkownika nie obsługuje aplikacji SameSite None:

if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
    options.SameSite = SameSiteMode.Unspecified;
}

Poniższy kod przedstawia przykładową DisallowsSameSiteNone metodę:

Ostrzeżenie

Poniższy kod jest przeznaczony tylko dla pokazu:

  • Nie należy go uważać za ukończone.
  • Nie jest ona obsługiwana ani obsługiwana.
public static bool DisallowsSameSiteNone(string userAgent)
{
    // Check if a null or empty string has been passed in, since this
    // will cause further interrogation of the useragent to fail.
     if (String.IsNullOrWhiteSpace(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;
}

Testowanie aplikacji pod kątem problemów z usługą SameSite

Aplikacje, które wchodzą w interakcje z witrynami zdalnymi, takimi jak za pośrednictwem logowania innej firmy, muszą:

Przetestuj aplikacje internetowe przy użyciu wersji klienta, która może wyrazić zgodę na nowe zachowanie w witrynie SameSite. Chrome, Firefox i Chromium Edge mają nowe flagi funkcji, które mogą być używane do testowania. Gdy aplikacja zastosuje poprawki SameSite, przetestuj ją ze starszymi wersjami klienta, zwłaszcza w przeglądarce Safari. Aby uzyskać więcej informacji, zobacz Obsługa starszych przeglądarek w tym dokumencie.

Testowanie za pomocą przeglądarki Chrome

Chrome 78+ daje mylące wyniki, ponieważ ma tymczasowe środki zaradcze. Tymczasowe środki zaradcze w przeglądarce Chrome 78+ pozwalają na używanie plików cookie mniej niż dwie minuty. Chrome 76 lub 77 z włączonymi odpowiednimi flagami testowymi zapewnia dokładniejsze wyniki. Aby przetestować nowe zachowanie SameSite, przełączenie chrome://flags/#same-site-by-default-cookies na włączone. Starsze wersje programu Chrome (75 i starsze) są zgłaszane jako nieudane z nowym None ustawieniem. Zobacz Obsługa starszych przeglądarek w tym dokumencie.

Firma Google nie udostępnia starszych wersji chrome. Postępuj zgodnie z instrukcjami w temacie Pobierz Chromium , aby przetestować starsze wersje przeglądarki Chrome. Nie pobieraj przeglądarki Chrome z linków udostępnianych przez wyszukiwanie starszych wersji przeglądarki Chrome.

Począwszy od wersji 80.0.3975.0Canary, tymczasowe ograniczenie ryzyka Lax+POST można wyłączyć na potrzeby testowania przy użyciu nowej flagi --enable-features=SameSiteDefaultChecksMethodRigorously , aby umożliwić testowanie witryn i usług w ostatecznym stanie końcowym funkcji, w której usunięto środki zaradcze. Aby uzyskać więcej informacji, zobacz Chromium Projects SameSite Updates

Testowanie za pomocą przeglądarki Safari

Przeglądarka Safari 12 ściśle zaimplementowała poprzednią wersję roboczą i kończy się niepowodzeniem, gdy nowa None wartość znajduje się w obiekcie cookie. None jest unikany za pośrednictwem kodu wykrywania przeglądarki Obsługa starszych przeglądarek w tym dokumencie. Przetestuj identyfikatory logowania w stylu systemu operacyjnego oparte na przeglądarce Safari 12, Safari 13 i WebKit przy użyciu bibliotek MSAL, ADAL lub dowolnej używanej biblioteki. Problem jest zależny od bazowej wersji systemu operacyjnego. OSX Mojave (10.14) i iOS 12 są znane z problemów ze zgodnością z nowym zachowaniem SameSite. Uaktualnienie systemu operacyjnego do systemu OSX Catalina (10.15) lub iOS 13 rozwiązuje problem. Przeglądarka Safari nie ma obecnie flagi zgody na testowanie nowego zachowania specyfikacji.

Testowanie za pomocą przeglądarki Firefox

Obsługa przeglądarki Firefox dla nowego standardu można przetestować w wersji 68 lub nowszej, decydując się na about:config stronę z flagą network.cookie.sameSite.laxByDefaultfunkcji . Nie odnotowano raportów dotyczących problemów ze zgodnością ze starszymi wersjami przeglądarki Firefox.

Testowanie za pomocą przeglądarki Edge

Przeglądarka Edge obsługuje stary standard SameSite. Przeglądarka Edge w wersji 44 nie ma żadnych znanych problemów ze zgodnością z nowym standardem.

Testowanie za pomocą przeglądarki Edge (Chromium)

Flagi SameSite są ustawiane na edge://flags/#same-site-by-default-cookies stronie. Nie odnaleziono żadnych problemów ze zgodnością z przeglądarką Edge Chromium.

Testowanie za pomocą polecenia Electron

Electron Wersje obejmują starsze wersje Chromium. Na przykład wersja Electron używana przez aplikację Teams to Chromium 66, która wykazuje starsze zachowanie. Musisz przeprowadzić własne testy zgodności z wersją używanego Electron produktu. Zobacz Obsługa starszych przeglądarek w poniższej sekcji.

Dodatkowe zasoby

Przykład Dokument
.NET Core Razor Pages przykład ASP.NET Core 3.1 Razor Pages SameSite cookie

Można pobrać i przetestować następujące przykłady:

Przykład Dokument
.NET Core MVC przykład ASP.NET Core 2.1 MVC SameSite cookie
.NET Core Razor Pages przykład ASP.NET Core 2.1 Razor Pages SameSite cookie

Zmiany zachowania poprawki z grudnia

Konkretna zmiana zachowania dla programów .NET Framework i .NET Core 2.1 polega na SameSite tym, jak właściwość interpretuje None wartość. Przed poprawką wartość None oznaczaną "Nie emituj atrybutu w ogóle", po poprawce oznacza to "Emituj atrybut z wartością None". Po poprawce SameSite wartość parametru (SameSiteMode)(-1) powoduje, że atrybut nie jest emitowany.

Domyślna wartość SameSite dla plików cookie uwierzytelniania formularzy i stanu sesji została zmieniona z None na Lax.

Użycie interfejsu API w usłudze SameSite

Wartości domyślne HttpContext.Response.Cookies.Append mają wartość Unspecified, co oznacza, że do elementu nie dodano atrybutu cookie SameSite, a klient będzie używać jego domyślnego zachowania (Lax dla nowych przeglądarek, Brak dla starych). Poniższy kod pokazuje, jak zmienić cookie wartość SameSite na SameSiteMode.Lax:

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

Wszystkie składniki ASP.NET Core, które emitują pliki cookie, zastępują poprzednie wartości domyślne ustawieniami odpowiednimi dla ich scenariuszy. Przesłonięć powyższe wartości domyślne nie zostały zmienione.

Składnik cookie Wartość domyślna
CookieBuilder SameSite Unspecified
Session SessionOptions.Cookie Lax
CookieTempDataProvider CookieTempDataProviderOptions.Cookie Lax
IAntiforgery AntiforgeryOptions.Cookie Strict
Cookie Uwierzytelnianie CookieAuthenticationOptions.Cookie Lax
AddTwitter TwitterOptions.StateCookie Lax
RemoteAuthenticationHandler<TOptions> RemoteAuthenticationOptions.CorrelationCookie None
AddOpenIdConnect OpenIdConnectOptions.NonceCookie None
HttpContext.Response.Cookies.Append CookieOptions Unspecified

Historia i zmiany

Obsługa sameSite została po raz pierwszy zaimplementowana w programie ASP.NET Core w wersji 2.0 przy użyciu standardu roboczego 2016. Standard 2016 był opt-in. ASP.NET Core , domyślnie ustawiając kilka plików cookie Lax . Po wystąpieniu kilku problemów z uwierzytelnianiem większość użycia witryny SameSite została wyłączona.

Poprawki zostały wydane w listopadzie 2019 r. w celu zaktualizowania standardu z 2016 r. do standardu 2019. Wersja robocza z 2019 r. specyfikacji SameSite:

  • Nie jest do tyłu zgodny z wersją roboczą z 2016 roku. Aby uzyskać więcej informacji, zobacz Obsługa starszych przeglądarek w tym dokumencie.
  • Określa, że pliki cookie są domyślnie traktowane jako SameSite=Lax .
  • Określa pliki cookie, które jawnie asertywne SameSite=None w celu włączenia dostarczania między witrynami powinny być oznaczone jako Secure. None jest nowym wpisem, aby zrezygnować.
  • Jest obsługiwany przez poprawki wydane dla ASP.NET Core 2.1, 2.2 i 3.0. ASP.NET Core 3.1 ma dodatkową obsługę usługi SameSite.
  • Program Chrome ma być domyślnie włączony w lutym 2020 roku. Przeglądarki zaczęły przechodzić do tego standardu w 2019 roku.

Interfejsy API, których dotyczy zmiana z wersji roboczej SameSite z 2016 r. do wersji roboczej standardu z 2019 r.

Obsługa starszych przeglądarek

Standard SameSite z 2016 r. nakazuje traktowanie nieznanych wartości jako SameSite=Strict wartości. Aplikacje dostępne ze starszych przeglądarek, które obsługują standard SameSite 2016, mogą ulec awarii, gdy otrzymają właściwość SameSite o wartości None. Aplikacje internetowe muszą implementować wykrywanie przeglądarki, jeśli zamierzają obsługiwać starsze przeglądarki. ASP.NET Core nie implementuje wykrywania przeglądarki, ponieważ wartości agentów użytkowników są bardzo niestabilne i często zmieniają się. Punkt rozszerzenia umożliwia Microsoft.AspNetCore.CookiePolicy podłączanie logiki specyficznej dla agenta użytkownika.

W Startup.Configurepliku dodaj kod wywołujący UseCookiePolicy przed wywołaniem UseAuthentication metody lub dowolną metodę zapisującą pliki cookie:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseCookiePolicy();
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

W Startup.ConfigureServicespliku dodaj kod podobny do następującego:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.MinimumSameSitePolicy = (SameSiteMode)(-1);
        options.OnAppendCookie = cookieContext =>
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
        options.OnDeleteCookie = cookieContext =>
            CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
    });

    services.AddRazorPages();
}

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

    }
}

W poprzednim przykładzie jest to biblioteka dostarczana przez użytkownika, która wykrywa, MyUserAgentDetectionLib.DisallowsSameSiteNone czy agent użytkownika nie obsługuje aplikacji SameSite None:

if (MyUserAgentDetectionLib.DisallowsSameSiteNone(userAgent))
{
    options.SameSite = SameSiteMode.Unspecified;
}

Poniższy kod przedstawia przykładową DisallowsSameSiteNone metodę:

Ostrzeżenie

Poniższy kod jest przeznaczony tylko dla pokazu:

  • Nie należy go uważać za ukończone.
  • Nie jest ona obsługiwana ani obsługiwana.
public static bool DisallowsSameSiteNone(string userAgent)
{
    // Check if a null or empty string has been passed in, since this
    // will cause further interrogation of the useragent to fail.
     if (String.IsNullOrWhiteSpace(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;
}

Testowanie aplikacji pod kątem problemów z usługą SameSite

Aplikacje, które wchodzą w interakcje z witrynami zdalnymi, takimi jak za pośrednictwem logowania innej firmy, muszą:

Przetestuj aplikacje internetowe przy użyciu wersji klienta, która może wyrazić zgodę na nowe zachowanie w witrynie SameSite. Chrome, Firefox i Chromium Edge mają nowe flagi funkcji, które mogą być używane do testowania. Gdy aplikacja zastosuje poprawki SameSite, przetestuj ją ze starszymi wersjami klienta, zwłaszcza w przeglądarce Safari. Aby uzyskać więcej informacji, zobacz Obsługa starszych przeglądarek w tym dokumencie.

Testowanie za pomocą przeglądarki Chrome

Chrome 78+ daje mylące wyniki, ponieważ ma tymczasowe środki zaradcze. Tymczasowe środki zaradcze w przeglądarce Chrome 78+ pozwalają na używanie plików cookie mniej niż dwie minuty. Chrome 76 lub 77 z włączonymi odpowiednimi flagami testowymi zapewnia dokładniejsze wyniki. Aby przetestować nowe zachowanie SameSite, przełączenie chrome://flags/#same-site-by-default-cookies na włączone. Starsze wersje programu Chrome (75 i starsze) są zgłaszane jako nieudane z nowym None ustawieniem. Zobacz Obsługa starszych przeglądarek w tym dokumencie.

Firma Google nie udostępnia starszych wersji chrome. Postępuj zgodnie z instrukcjami w temacie Pobierz Chromium , aby przetestować starsze wersje przeglądarki Chrome. Nie pobieraj przeglądarki Chrome z linków udostępnianych przez wyszukiwanie starszych wersji przeglądarki Chrome.

Począwszy od wersji 80.0.3975.0Canary, tymczasowe ograniczenie ryzyka Lax+POST można wyłączyć na potrzeby testowania przy użyciu nowej flagi --enable-features=SameSiteDefaultChecksMethodRigorously , aby umożliwić testowanie witryn i usług w ostatecznym stanie końcowym funkcji, w której usunięto środki zaradcze. Aby uzyskać więcej informacji, zobacz Chromium Projects SameSite Updates

Testowanie za pomocą przeglądarki Safari

Przeglądarka Safari 12 ściśle zaimplementowała poprzednią wersję roboczą i kończy się niepowodzeniem, gdy nowa None wartość znajduje się w obiekcie cookie. None jest unikany za pośrednictwem kodu wykrywania przeglądarki Obsługa starszych przeglądarek w tym dokumencie. Przetestuj identyfikatory logowania w stylu systemu operacyjnego oparte na przeglądarce Safari 12, Safari 13 i WebKit przy użyciu bibliotek MSAL, ADAL lub dowolnej używanej biblioteki. Problem jest zależny od bazowej wersji systemu operacyjnego. OSX Mojave (10.14) i iOS 12 są znane z problemów ze zgodnością z nowym zachowaniem SameSite. Uaktualnienie systemu operacyjnego do systemu OSX Catalina (10.15) lub iOS 13 rozwiązuje problem. Przeglądarka Safari nie ma obecnie flagi zgody na testowanie nowego zachowania specyfikacji.

Testowanie za pomocą przeglądarki Firefox

Obsługa przeglądarki Firefox dla nowego standardu można przetestować w wersji 68 lub nowszej, decydując się na about:config stronę z flagą network.cookie.sameSite.laxByDefaultfunkcji . Nie odnotowano raportów dotyczących problemów ze zgodnością ze starszymi wersjami przeglądarki Firefox.

Testowanie za pomocą przeglądarki Edge

Przeglądarka Edge obsługuje stary standard SameSite. Przeglądarka Edge w wersji 44 nie ma żadnych znanych problemów ze zgodnością z nowym standardem.

Testowanie za pomocą przeglądarki Edge (Chromium)

Flagi SameSite są ustawiane na edge://flags/#same-site-by-default-cookies stronie. Nie odnaleziono żadnych problemów ze zgodnością z przeglądarką Edge Chromium.

Testowanie za pomocą polecenia Electron

Electron Wersje obejmują starsze wersje Chromium. Na przykład wersja Electron używana przez aplikację Teams to Chromium 66, która wykazuje starsze zachowanie. Musisz przeprowadzić własne testy zgodności z wersją używanego Electron produktu. Zobacz Obsługa starszych przeglądarek w poniższej sekcji.

Dodatkowe zasoby

Przykład Dokument
.NET Core MVC przykład ASP.NET Core 2.1 MVC SameSite cookie
.NET Core Razor Pages przykład ASP.NET Core 2.1 Razor Pages SameSite cookie