Работа с SameSite cookies в ASP.NET Core

Автор: Рик Андерсон (Rick Anderson)

SameSite — это стандартный проект IETF, предназначенный для обеспечения некоторой защиты от атак на межсайтовые подделки (CSRF). Первоначально проект был составлен в 2016 году, проект стандарта был обновлен в 2019 году. Обновленный стандарт не совместим с предыдущим стандартом, что является наиболее заметным отличием:

  • CookieS без заголовка SameSite обрабатываются как SameSite=Lax по умолчанию.
  • SameSite=None необходимо использовать для разрешения использования между сайтами cookie .
  • Cookies, что утверждение SameSite=None должно также быть отмечено как Secure.
  • Приложения, которые используются<iframe>, могут столкнуться с проблемами или с нимиcookiesameSite=LaxsameSite=Strict, так как <iframe> рассматриваются как межсайтовые сценарии.
  • Значение SameSite=None не допускается стандартом2016 года и приводит к тому, что некоторые реализации будут рассматриваться как.cookieSameSite=Strict См. статью "Поддержка старых браузеров " в этом документе.

Этот SameSite=Lax параметр подходит для большинства приложений cookie. Некоторые формы проверки подлинности, такие как OpenID Подключение (OIDC) и WS-Federation по умолчанию для перенаправлений на основе POST. Перенаправление на основе POST активирует защиту браузера SameSite, поэтому Для этих компонентов отключается Тот же сайт. Большинство имен входа OAuth не затрагиваются из-за различий в том, как потоки запросов.

Каждый компонент ASP.NET Core, который выдает cookies, должен решить, подходит ли тот же сайт.

SameSite и Identity

ASP.NET Core Identity в значительной степени не влияет на тот же сайтcookie, за исключением расширенных сценариев, таких как IFrames или OpenIdConnect интеграция.

При использовании Identityне добавляйте cookie поставщиков и не вызывайте services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)их. Identity

Пример кода теста SameSite

Следующий пример можно скачать и проверить:

Пример Документ
Страницы .NET Core Razor пример ASP.NET Core 3.1 Razor Pages SameSite cookie

Поддержка .NET Core для того же атрибута.

.NET Core поддерживает стандартный проект 2019 для SameSite. Разработчики могут программно управлять значением того же атрибутаSite с помощью HttpCookie.SameSite свойства. SameSite Задание свойства Strict, Laxили None приводит к тому, что эти значения записываются в сети с cookieпомощью . Параметр, указывающий SameSiteMode.Unspecified , что один и тот же сайт не должен отправляться с 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);
}

Использование API с SameSite

HttpContext.Response.CookieЗначение по умолчанию s.Add по Unspecifiedумолчанию означает, что атрибут SameSite, добавленный в приложение cookie , и клиент будет использовать его поведение по умолчанию (Lax для новых браузеров, None для старых). В следующем коде показано, как изменить значение SameSite cookie на SameSiteMode.Lax:

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

Все компоненты ASP.NET Core, которые переопределяют cookieпредыдущие значения по умолчанию с параметрами, соответствующими их сценариям. Переопределенные предыдущие значения по умолчанию не изменились.

Компонент cookie По умолчанию.
CookieBuilder SameSite Unspecified
Session SessionOptions.Cookie Lax
CookieTempDataProvider CookieTempDataProviderOptions.Cookie Lax
IAntiforgery AntiforgeryOptions.Cookie Strict
Cookie Проверка подлинности CookieAuthenticationOptions.Cookie Lax
AddTwitter TwitterOptions.StateCookie Lax
RemoteAuthenticationHandler<TOptions> RemoteAuthenticationOptions.CorrelationCookie None
AddOpenIdConnect OpenId Подключение Options.NonceCookie None
HttpContext.Response.Cookies.Append CookieOptions Unspecified

ASP.NET Core 3.1 и более поздних версий предоставляет следующую поддержку SameSite:

  • Переопределяет поведение выдачи SameSiteMode.NoneSameSite=None
  • Добавляет новое значение SameSiteMode.Unspecified для пропуска атрибута SameSite.
  • Все cookieAPI-интерфейсы по умолчанию Unspecified. Некоторые компоненты, использующие cookieзначения набора, более характерные для их сценариев. Примеры см. в приведенной выше таблице.

В ASP.NET Core 3.0 и более поздних версий значения по умолчанию SameSite были изменены, чтобы избежать конфликтов с несогласованными значениями по умолчанию клиента. Следующие API изменили значение по умолчанию SameSiteMode.Lax , чтобы -1 избежать создания атрибута SameSite для этих s cookie:

Журнал и изменения

Поддержка SameSite была впервые реализована в ASP.NET Core в версии 2.0 с использованием стандартного проекта 2016 года. Стандарт 2016 года был отклонен. ASP.NET Core, выбрав несколько cookies по Lax умолчанию. После возникновения нескольких проблем с проверкой подлинности большинство использования SameSite было отключено.

Исправления были выпущены в ноябре 2019 года, чтобы обновить стандарт 2016 года до стандарта 2019 года. Проект спецификации SameSite в 2019 году:

  • Не совместим с черновиком 2016 года. Дополнительные сведения см. в разделе "Поддержка старых браузеров " в этом документе.
  • Указывает, что значения cookies обрабатываются по SameSite=Lax умолчанию.
  • Указывает, cookieчто явное утверждение SameSite=None для включения доставки между сайтами должно быть отмечено как Secure. None является новой записью, чтобы отказаться.
  • Поддерживается исправлениями, выпущенными для ASP.NET Core 2.1, 2.2 и 3.0. ASP.NET Core 3.1 и более поздних версий имеет дополнительную поддержку SameSite.
  • Планируется включить Chrome по умолчанию в феврале 2020 года. Браузеры начали переходить к этому стандарту в 2019 году.

API, затронутые изменением стандарта 2016 SameSite в стандарт 2019 г.

Поддержка старых браузеров

Стандарт 2016 SameSite подтвердил, что неизвестные значения должны рассматриваться как SameSite=Strict значения. Приложения, доступные из старых браузеров, которые поддерживают стандарт SameSite 2016, могут нарушиться при получении свойства SameSite со значением None. Веб-приложения должны реализовать обнаружение браузеров, если они намерены поддерживать старые браузеры. ASP.NET Core не реализует обнаружение браузера, так как значения пользовательских агентов являются очень неустойчивыми и часто изменяются. Точка Microsoft.AspNetCore.CookiePolicy расширения позволяет подключаться к логике конкретного агента пользователя.

Добавьте Program.csкод, который вызывается UseCookiePolicy перед вызовом UseAuthentication или любым методом, который записывает 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();

Добавьте Program.csкод, аналогичный следующему выделенному коду:

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();

В предыдущем примере представлена пользовательская библиотека, которая определяет, MyUserAgentDetectionLib.DisallowsSameSiteNone не поддерживает ли агент пользователя тот же сайт None:

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

В следующем коде показан пример DisallowsSameSiteNone метода:

Предупреждение

Следующий код предназначен только для демонстрации:

  • Его не следует считать полным.
  • Он не поддерживается или не поддерживается.
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;
}

Тестирование приложений для проблем с SameSite

Приложения, взаимодействующие с удаленными сайтами, например с помощью стороннего входа, должны:

Тестирование веб-приложений с помощью клиентской версии, которая может принять участие в новом поведении SameSite. 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 не делает более старые версии хрома доступными. Следуйте инструкциям в разделе "Скачать Chromium" , чтобы протестировать старые версии Chrome. Не скачивайте Chrome из ссылок, предоставляемых поиском более старых версий хрома.

Начиная с канарской версии 80.0.3975.0, временное устранение рисков Lax+POST можно отключить для тестирования с помощью нового флага --enable-features=SameSiteDefaultChecksMethodRigorously , чтобы разрешить тестирование сайтов и служб в конечном итоге состояния функции, в которой была удалена устранение рисков. Дополнительные сведения см. в разделе "Chromium Projects SameSite" Обновления

Тестирование с помощью Safari

Safari 12 строго реализует предыдущий черновик и завершается ошибкойcookie, если новое None значение находится в . None Не используется код обнаружения браузера, поддерживающий старые браузеры в этом документе. Проверьте имена входа в стиль ОС на основе Safari 12, Safari 13 и WebKit с помощью MSAL, ADAL или любой используемой библиотеки. Эта проблема зависит от базовой версии ОС. OSX Mojave (10.14) и iOS 12, как известно, имеют проблемы совместимости с новым поведением SameSite. Обновление ОС до OSX Catalina (10.15) или iOS 13 устраняет проблему. В настоящее время Safari не имеет флаг согласия на тестирование нового поведения спецификации.

Тестирование с помощью Firefox

Поддержка Firefox для нового стандарта может быть проверена на версии 68+ путем согласия на about:config странице с флагом network.cookie.sameSite.laxByDefaultфункции. Не было отчетов о проблемах совместимости с более старыми версиями Firefox.

Тестирование с помощью браузера Edge

Edge поддерживает старый стандарт SameSite. У пограничных версий 44 нет известных проблем совместимости с новым стандартом.

Тестирование с помощью Edge (Chromium)

На странице задаются edge://flags/#same-site-by-default-cookies флаги SameSite. Проблемы совместимости не обнаружены с пограничным Chromium.

Тестирование с помощью Electron

Electron Версии включают более старые версии Chromium. Например, версия Electron , используемая Teams, — Chromium 66, которая демонстрирует старое поведение. Необходимо выполнить собственное тестирование совместимости с версией используемого Electron продукта. См . раздел "Поддержка старых браузеров " в следующем разделе.

Дополнительные ресурсы

Пример Документ
Страницы .NET Core Razor пример ASP.NET Core 3.1 Razor Pages SameSite cookie

Следующий пример можно скачать и проверить:

Пример Документ
Страницы .NET Core Razor пример ASP.NET Core 3.1 Razor Pages SameSite cookie

Поддержка .NET Core для того же атрибута.

.NET Core 3.1 и более поздних версий поддерживают стандарт 2019 для SameSite. Разработчики могут программно управлять значением того же атрибутаSite с помощью HttpCookie.SameSite свойства. SameSite Задание свойства Strict, Lax или None приводит к записи этих значений в сети с помощью параметра cookie. Задание равно, указывающее (SameSiteMode)(-1) , что в сети не должен быть включен ни один атрибут одного и того же сайта. 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);

.NET Core 3.1 и более поздних версий поддерживают обновленные значения SameSite и добавляют дополнительное значение перечисления в SameSiteMode.Unspecified перечисление SameSiteMode . Это новое значение указывает, что с ним не должен отправляться cookieтот же сайт.

Использование API с SameSite

HttpContext.Response.CookieЗначение по умолчанию s.Add по Unspecifiedумолчанию означает, что атрибут SameSite, добавленный в приложение cookie , и клиент будет использовать его поведение по умолчанию (Lax для новых браузеров, None для старых). В следующем коде показано, как изменить значение SameSite cookie на SameSiteMode.Lax:

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

Все компоненты ASP.NET Core, которые переопределяют cookieпредыдущие значения по умолчанию с параметрами, соответствующими их сценариям. Переопределенные предыдущие значения по умолчанию не изменились.

Компонент cookie По умолчанию.
CookieBuilder SameSite Unspecified
Session SessionOptions.Cookie Lax
CookieTempDataProvider CookieTempDataProviderOptions.Cookie Lax
IAntiforgery AntiforgeryOptions.Cookie Strict
Cookie Проверка подлинности CookieAuthenticationOptions.Cookie Lax
AddTwitter TwitterOptions.StateCookie Lax
RemoteAuthenticationHandler<TOptions> RemoteAuthenticationOptions.CorrelationCookie None
AddOpenIdConnect OpenId Подключение Options.NonceCookie None
HttpContext.Response.Cookies.Append CookieOptions Unspecified

ASP.NET Core 3.1 и более поздних версий предоставляет следующую поддержку SameSite:

  • Переопределяет поведение выдачи SameSiteMode.NoneSameSite=None
  • Добавляет новое значение SameSiteMode.Unspecified для пропуска атрибута SameSite.
  • Все cookieAPI-интерфейсы по умолчанию Unspecified. Некоторые компоненты, использующие cookieзначения набора, более характерные для их сценариев. Примеры см. в приведенной выше таблице.

В ASP.NET Core 3.0 и более поздних версий значения по умолчанию SameSite были изменены, чтобы избежать конфликтов с несогласованными значениями по умолчанию клиента. Следующие API изменили значение по умолчанию SameSiteMode.Lax , чтобы -1 избежать создания атрибута SameSite для этих s cookie:

Журнал и изменения

Поддержка SameSite была впервые реализована в ASP.NET Core в версии 2.0 с использованием стандартного проекта 2016 года. Стандарт 2016 года был отклонен. ASP.NET Core, выбрав несколько cookies по Lax умолчанию. После возникновения нескольких проблем с проверкой подлинности большинство использования SameSite было отключено.

Исправления были выпущены в ноябре 2019 года, чтобы обновить стандарт 2016 года до стандарта 2019 года. Проект спецификации SameSite в 2019 году:

  • Не совместим с черновиком 2016 года. Дополнительные сведения см. в разделе "Поддержка старых браузеров " в этом документе.
  • Указывает, что значения cookies обрабатываются по SameSite=Lax умолчанию.
  • Указывает, cookieчто явное утверждение SameSite=None для включения доставки между сайтами должно быть отмечено как Secure. None является новой записью, чтобы отказаться.
  • Поддерживается исправлениями, выпущенными для ASP.NET Core 2.1, 2.2 и 3.0. ASP.NET Core 3.1 имеет дополнительную поддержку SameSite.
  • Планируется включить Chrome по умолчанию в феврале 2020 года. Браузеры начали переходить к этому стандарту в 2019 году.

API, затронутые изменением стандарта 2016 SameSite в стандарт 2019 г.

Поддержка старых браузеров

Стандарт 2016 SameSite подтвердил, что неизвестные значения должны рассматриваться как SameSite=Strict значения. Приложения, доступные из старых браузеров, которые поддерживают стандарт SameSite 2016, могут нарушиться при получении свойства SameSite со значением None. Веб-приложения должны реализовать обнаружение браузеров, если они намерены поддерживать старые браузеры. ASP.NET Core не реализует обнаружение браузера, так как значения пользовательских агентов являются очень неустойчивыми и часто изменяются. Точка Microsoft.AspNetCore.CookiePolicy расширения позволяет подключаться к логике конкретного агента пользователя.

Добавьте Startup.Configureкод, который вызывается UseCookiePolicy перед вызовом UseAuthentication или любым методом, который записывает 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();
    });
}

Добавьте Startup.ConfigureServicesкод, аналогичный следующему:

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;
        }
    }
}

В предыдущем примере представлена пользовательская библиотека, которая определяет, MyUserAgentDetectionLib.DisallowsSameSiteNone не поддерживает ли агент пользователя тот же сайт None:

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

В следующем коде показан пример DisallowsSameSiteNone метода:

Предупреждение

Следующий код предназначен только для демонстрации:

  • Его не следует считать полным.
  • Он не поддерживается или не поддерживается.
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;
}

Тестирование приложений для проблем с SameSite

Приложения, взаимодействующие с удаленными сайтами, например с помощью стороннего входа, должны:

Тестирование веб-приложений с помощью клиентской версии, которая может принять участие в новом поведении SameSite. 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 не делает более старые версии хрома доступными. Следуйте инструкциям в разделе "Скачать Chromium" , чтобы протестировать старые версии Chrome. Не скачивайте Chrome из ссылок, предоставляемых поиском более старых версий хрома.

Начиная с канарской версии 80.0.3975.0, временное устранение рисков Lax+POST можно отключить для тестирования с помощью нового флага --enable-features=SameSiteDefaultChecksMethodRigorously , чтобы разрешить тестирование сайтов и служб в конечном итоге состояния функции, в которой была удалена устранение рисков. Дополнительные сведения см. в разделе "Chromium Projects SameSite" Обновления

Тестирование с помощью Safari

Safari 12 строго реализует предыдущий черновик и завершается ошибкойcookie, если новое None значение находится в . None Не используется код обнаружения браузера, поддерживающий старые браузеры в этом документе. Проверьте имена входа в стиль ОС на основе Safari 12, Safari 13 и WebKit с помощью MSAL, ADAL или любой используемой библиотеки. Эта проблема зависит от базовой версии ОС. OSX Mojave (10.14) и iOS 12, как известно, имеют проблемы совместимости с новым поведением SameSite. Обновление ОС до OSX Catalina (10.15) или iOS 13 устраняет проблему. В настоящее время Safari не имеет флаг согласия на тестирование нового поведения спецификации.

Тестирование с помощью Firefox

Поддержка Firefox для нового стандарта может быть проверена на версии 68+ путем согласия на about:config странице с флагом network.cookie.sameSite.laxByDefaultфункции. Не было отчетов о проблемах совместимости с более старыми версиями Firefox.

Тестирование с помощью браузера Edge

Edge поддерживает старый стандарт SameSite. У пограничных версий 44 нет известных проблем совместимости с новым стандартом.

Тестирование с помощью Edge (Chromium)

На странице задаются edge://flags/#same-site-by-default-cookies флаги SameSite. Проблемы совместимости не обнаружены с пограничным Chromium.

Тестирование с помощью Electron

Electron Версии включают более старые версии Chromium. Например, версия Electron , используемая Teams, — Chromium 66, которая демонстрирует старое поведение. Необходимо выполнить собственное тестирование совместимости с версией используемого Electron продукта. См . раздел "Поддержка старых браузеров " в следующем разделе.

Дополнительные ресурсы

Пример Документ
Страницы .NET Core Razor пример ASP.NET Core 3.1 Razor Pages SameSite cookie

Можно скачать и проверить следующие примеры:

Пример Документ
MVC .NET Core пример MVC SameSite cookie ASP.NET Core 2.1
Страницы .NET Core Razor пример ASP.NET Core 2.1 Razor Pages SameSite cookie

Изменения в поведении исправлений за декабрь

Изменение конкретного поведения для платформа .NET Framework и .NET Core 2.1 заключается в том, как SameSite свойство интерпретирует None значение. Перед исправлением значение None означает "Не выдавать атрибут вообще", после исправления оно означает "Выпустить атрибут со значением None". После исправления SameSite значение (SameSiteMode)(-1) атрибута не будет выдаваться.

Значение sameSite по умолчанию для проверки подлинности форм и состояния cookieсеанса было изменено на NoneLax.

Использование API с SameSite

HttpContext.Response.CookieЗначение по умолчанию s.Add по Unspecifiedумолчанию означает, что атрибут SameSite, добавленный в приложение cookie , и клиент будет использовать его поведение по умолчанию (Lax для новых браузеров, None для старых). В следующем коде показано, как изменить значение SameSite cookie на SameSiteMode.Lax:

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

Все компоненты ASP.NET Core, которые переопределяют cookieпредыдущие значения по умолчанию с параметрами, соответствующими их сценариям. Переопределенные предыдущие значения по умолчанию не изменились.

Компонент cookie По умолчанию.
CookieBuilder SameSite Unspecified
Session SessionOptions.Cookie Lax
CookieTempDataProvider CookieTempDataProviderOptions.Cookie Lax
IAntiforgery AntiforgeryOptions.Cookie Strict
Cookie Проверка подлинности CookieAuthenticationOptions.Cookie Lax
AddTwitter TwitterOptions.StateCookie Lax
RemoteAuthenticationHandler<TOptions> RemoteAuthenticationOptions.CorrelationCookie None
AddOpenIdConnect OpenId Подключение Options.NonceCookie None
HttpContext.Response.Cookies.Append CookieOptions Unspecified

Журнал и изменения

Поддержка SameSite была впервые реализована в ASP.NET Core в версии 2.0 с использованием стандартного проекта 2016 года. Стандарт 2016 года был отклонен. ASP.NET Core, выбрав несколько cookies по Lax умолчанию. После возникновения нескольких проблем с проверкой подлинности большинство использования SameSite было отключено.

Исправления были выпущены в ноябре 2019 года, чтобы обновить стандарт 2016 года до стандарта 2019 года. Проект спецификации SameSite в 2019 году:

  • Не совместим с черновиком 2016 года. Дополнительные сведения см. в разделе "Поддержка старых браузеров " в этом документе.
  • Указывает, что значения cookies обрабатываются по SameSite=Lax умолчанию.
  • Указывает, cookieчто явное утверждение SameSite=None для включения доставки между сайтами должно быть отмечено как Secure. None является новой записью, чтобы отказаться.
  • Поддерживается исправлениями, выпущенными для ASP.NET Core 2.1, 2.2 и 3.0. ASP.NET Core 3.1 имеет дополнительную поддержку SameSite.
  • Планируется включить Chrome по умолчанию в феврале 2020 года. Браузеры начали переходить к этому стандарту в 2019 году.

API, затронутые изменением стандарта 2016 SameSite в стандарт 2019 г.

Поддержка старых браузеров

Стандарт 2016 SameSite подтвердил, что неизвестные значения должны рассматриваться как SameSite=Strict значения. Приложения, доступные из старых браузеров, которые поддерживают стандарт SameSite 2016, могут нарушиться при получении свойства SameSite со значением None. Веб-приложения должны реализовать обнаружение браузеров, если они намерены поддерживать старые браузеры. ASP.NET Core не реализует обнаружение браузера, так как значения пользовательских агентов являются очень неустойчивыми и часто изменяются. Точка Microsoft.AspNetCore.CookiePolicy расширения позволяет подключаться к логике конкретного агента пользователя.

Добавьте Startup.Configureкод, который вызывается UseCookiePolicy перед вызовом UseAuthentication или любым методом, который записывает 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();
    });
}

Добавьте Startup.ConfigureServicesкод, аналогичный следующему:

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);
        }

    }
}

В предыдущем примере представлена пользовательская библиотека, которая определяет, MyUserAgentDetectionLib.DisallowsSameSiteNone не поддерживает ли агент пользователя тот же сайт None:

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

В следующем коде показан пример DisallowsSameSiteNone метода:

Предупреждение

Следующий код предназначен только для демонстрации:

  • Его не следует считать полным.
  • Он не поддерживается или не поддерживается.
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;
}

Тестирование приложений для проблем с SameSite

Приложения, взаимодействующие с удаленными сайтами, например с помощью стороннего входа, должны:

Тестирование веб-приложений с помощью клиентской версии, которая может принять участие в новом поведении SameSite. 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 не делает более старые версии хрома доступными. Следуйте инструкциям в разделе "Скачать Chromium" , чтобы протестировать старые версии Chrome. Не скачивайте Chrome из ссылок, предоставляемых поиском более старых версий хрома.

Начиная с канарской версии 80.0.3975.0, временное устранение рисков Lax+POST можно отключить для тестирования с помощью нового флага --enable-features=SameSiteDefaultChecksMethodRigorously , чтобы разрешить тестирование сайтов и служб в конечном итоге состояния функции, в которой была удалена устранение рисков. Дополнительные сведения см. в разделе "Chromium Projects SameSite" Обновления

Тестирование с помощью Safari

Safari 12 строго реализует предыдущий черновик и завершается ошибкойcookie, если новое None значение находится в . None Не используется код обнаружения браузера, поддерживающий старые браузеры в этом документе. Проверьте имена входа в стиль ОС на основе Safari 12, Safari 13 и WebKit с помощью MSAL, ADAL или любой используемой библиотеки. Эта проблема зависит от базовой версии ОС. OSX Mojave (10.14) и iOS 12, как известно, имеют проблемы совместимости с новым поведением SameSite. Обновление ОС до OSX Catalina (10.15) или iOS 13 устраняет проблему. В настоящее время Safari не имеет флаг согласия на тестирование нового поведения спецификации.

Тестирование с помощью Firefox

Поддержка Firefox для нового стандарта может быть проверена на версии 68+ путем согласия на about:config странице с флагом network.cookie.sameSite.laxByDefaultфункции. Не было отчетов о проблемах совместимости с более старыми версиями Firefox.

Тестирование с помощью браузера Edge

Edge поддерживает старый стандарт SameSite. У пограничных версий 44 нет известных проблем совместимости с новым стандартом.

Тестирование с помощью Edge (Chromium)

На странице задаются edge://flags/#same-site-by-default-cookies флаги SameSite. Проблемы совместимости не обнаружены с пограничным Chromium.

Тестирование с помощью Electron

Electron Версии включают более старые версии Chromium. Например, версия Electron , используемая Teams, — Chromium 66, которая демонстрирует старое поведение. Необходимо выполнить собственное тестирование совместимости с версией используемого Electron продукта. См . раздел "Поддержка старых браузеров " в следующем разделе.

Дополнительные ресурсы

Пример Документ
MVC .NET Core пример MVC SameSite cookie ASP.NET Core 2.1
Страницы .NET Core Razor пример ASP.NET Core 2.1 Razor Pages SameSite cookie