Файлы cookie SameSite и Открытый веб-интерфейс для .NET (OWIN)
Автор: Рик Андерсон (Rick Anderson)
SameSite
— это черновик IETF, предназначенный для обеспечения некоторой защиты от атак на межсайтовые подделки (CSRF). Черновик SameSite 2019:
- По умолчанию обрабатывает файлы cookie
SameSite=Lax
. - Указывает файлы cookie, которые явно утверждают
SameSite=None
для включения доставки между сайтами, должны быть помечены какSecure
.
Lax
работает для большинства файлов cookie приложений. Некоторые формы проверки подлинности, такие как OpenID Connect (OIDC) и WS-Federation по умолчанию перенаправления на основе POST. Перенаправление на основе POST активирует SameSite
защиту браузера, поэтому SameSite
для этих компонентов отключена. Большинство имен входа OAuth не затрагиваются из-за различий в том, как потоки запросов. Все остальные компоненты не задаются SameSite
по умолчанию и используют поведение клиентов по умолчанию (старое или новое).
Параметр None
вызывает проблемы совместимости с клиентами, реализующими предыдущий стандарт 2016 г . (например, iOS 12). См. статью "Поддержка старых браузеров " в этом документе.
Каждый компонент OWIN, который выдает файлы cookie, должен решить, подходит ли SameSite
это.
Сведения о ASP.NET версии 4.x этой статьи см. в разделе "Работа с файлами cookie SameSite" в ASP.NET.
Microsoft.Owin
имеет собственную SameSite
реализацию:
- Это не зависит напрямую от одного в
System.Web
. SameSite
работает на всех версиях, предназначенных дляMicrosoft.Owin
пакетов, .NET 4.5 и более поздних версий.- Только компонент SystemWebCookieManager напрямую взаимодействует с классом
System.Web
HttpCookie
.
SystemWebCookieManager
зависит от API .NET 4.7.2 System.Web
для включения SameSite
поддержки и исправлений для изменения поведения.
Причины использования SystemWebCookieManager
описаны в проблемах интеграции файлов cookie OWIN и System.Web Response. SystemWebCookieManager
рекомендуется при выполнении System.Web
в .
В следующем коде задано Lax
следующее значениеSameSite
:
owinContext.Response.Cookies.Append("My Key", "My Value", new CookieOptions()
{
SameSite = SameSiteMode.Lax
});
Используйте SameSite
следующие API:
- Microsoft.Owin.SameSiteMode
- CookieOptions.SameSite
- Класс CookieAuthenticationOptions
- CookieAuthenticationOptions.CookieSameSite
- ICookieManager
- SystemWebCookieManager
- SystemWebChunkingCookieManager
- CookieAuthenticationOptions.CookieManager
- OpenIdConnectAuthenticationOptions.CookieManager
Microsoft.Owin никогда не поддерживал SameSite
стандарт 2016 года.
Поддержка черновика SameSite 2019 доступна только в Microsoft.Owin
версии 4.1.0 и более поздних версий. Исправления для предыдущих версий отсутствуют.
Проект спецификации SameSite
за 2019 год:
- Не совместим с черновиком 2016 года. Дополнительные сведения см. в разделе "Поддержка старых браузеров " в этом документе.
- Указывает, что файлы cookie обрабатываются по
SameSite=Lax
умолчанию. - Указывает файлы cookie, которые явно утверждаются
SameSite=None
для включения доставки между сайтами, должны быть помечены какSecure
.None
является новой записью, чтобы отказаться. - Планируется включить Chrome по умолчанию в феврале 2020 года. Браузеры начали переходить к этому стандарту в 2019 году.
- Поддерживается исправлениями, выпущенными в статьях базы знаний. Дополнительные сведения см. в статьях базы знаний, поддерживающих SameSite в платформа .NET Framework.
Стандарт 2016 SameSite
года подтвердил, что неизвестные значения должны рассматриваться как SameSite=Strict
значения. Приложения, доступные из старых браузеров, поддерживающих стандарт 2016 SameSite
, могут нарушиться при получении SameSite
свойства со значением None
. Веб-приложения должны реализовать обнаружение браузеров, если они намерены поддерживать старые браузеры. ASP.NET не реализует обнаружение браузера, так как значения пользовательских агентов являются очень неустойчивыми и часто изменяются. Точка расширения в ICookieManager позволяет подключаться к логике конкретного агента пользователя.
Добавьте 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
поведении. Chrome, Firefox и Chromium Edge имеют новые флаги функций, которые можно использовать для тестирования. После применения SameSite
исправлений приложение протестирует его с помощью более старых клиентских версий, особенно Safari. Дополнительные сведения см. в разделе "Поддержка старых браузеров " в этом документе.
Chrome 78+ дает вводящие в заблуждение результаты, так как он имеет временное устранение рисков. Временное устранение рисков Chrome 78+ позволяет использовать файлы cookie менее чем за две минуты. Chrome 76 или 77 с соответствующими флагами тестирования обеспечивает более точные результаты. Чтобы проверить новое SameSite
поведение, chrome://flags/#same-site-by-default-cookies
включено. Более старые версии Chrome (75 и ниже) сообщаются о сбое с новым None
параметром. См. статью "Поддержка старых браузеров " в этом документе.
Google не делает более старые версии хрома доступными. Следуйте инструкциям в разделе "Скачать Chromium" , чтобы протестировать старые версии Chrome. Не скачивайте Chrome из ссылок, предоставляемых поиском более старых версий хрома.
Safari 12 строго реализует предыдущий черновик и завершается ошибкой, когда новое None
значение находится в файле cookie. None
Не используется код обнаружения браузера, поддерживающий старые браузеры в этом документе. Проверьте имена входа в стиль ОС на основе Safari 12, Safari 13 и WebKit с помощью MSAL или любой используемой библиотеки. Эта проблема зависит от базовой версии ОС. OSX Mojave (10.14) и iOS 12, как известно, имеют проблемы совместимости с новым SameSite
поведением. Обновление ОС до OSX Catalina (10.15) или iOS 13 устраняет проблему. В настоящее время Safari не имеет флаг согласия на тестирование нового поведения спецификации.
Поддержка Firefox для нового стандарта может быть проверена на версии 68+ путем согласия на about:config
странице с флагом network.cookie.sameSite.laxByDefault
функции. Не было отчетов о проблемах совместимости с более старыми версиями Firefox.
Edge поддерживает старый SameSite
стандарт. У пограничных версий 44 нет известных проблем совместимости с новым стандартом.
SameSite
флаги задаются на edge://flags/#same-site-by-default-cookies
странице. Проблемы совместимости не обнаружены с пограничным Chromium.
Версии Electron включают в себя более старые версии Chromium. Например, версия Electron, используемая Teams, — Chromium 66, которая демонстрирует старое поведение. Необходимо выполнить собственное тестирование совместимости с версией используемого продукта Electron. См . раздел "Поддержка старых браузеров " в следующем разделе.