Start Debugging

ASP.NET Core 11 Preview 6 включает автоматическую защиту от CSRF

Preview 6 по умолчанию отклоняет небезопасные межсайтовые запросы браузера, читая заголовок Sec-Fetch-Site вместо токена antiforgery. Вот что она блокирует и как исключить конечные точки.

.NET 11 Preview 6 вышла 2026-07-15, и изменение в ASP.NET Core, которое с наибольшей вероятностью затронет ваше приложение, не требует от вас ни строчки кода: защита от cross-site request forgery (CSRF) теперь включена по умолчанию, без конфигурации, в Minimal APIs, MVC, Razor Pages и Blazor. Она не полагается на классический токен antiforgery. Вместо этого она читает заголовок Sec-Fetch-Site браузера.

Почему танец с токеном стоило заменить

Старая модель возлагала бремя на вас. Вы выдавали токен antiforgery в каждую форму, проверяли его при POST и разделяли ключи Data Protection между экземплярами, чтобы токен по-прежнему расшифровывался после перехода через балансировщик нагрузки. Стоило забыть любой из этих шагов, и вы получали либо дыру в безопасности, либо ошибку во время выполнения (см. когда токен antiforgery не удалось расшифровать). Для API, у которых не было отрендеренной на сервере формы, чтобы прицепить к ней токен, руководство было ещё туманнее.

Fetch Metadata обходит всё это. Современные браузеры добавляют Sec-Fetch-Site к каждому запросу, и это значение нельзя подделать скриптом. Preview 6 проверяет его (используя заголовок Origin как запасной вариант) и фиксирует вердикт о доверии до того, как выполнится ваша конечная точка.

Что разрешается, а что отклоняется

Правило намеренно узкое. Запросы того же источника, инициированные пользователем переходы (ввод URL, клик по ссылке) и клиенты, не являющиеся браузерами (мобильное приложение, HttpClient, curl), разрешены все без исключения. Отклоняется же настоящая форма CSRF: межсайтовый запрос браузера, который пытается обратиться к одной из ваших конечных точек. Поскольку защита автоматическая, шаблоны Blazor Web App больше не вызывают app.UseAntiforgery().

Исключения остаются там, где они вам нужны. Публичный webhook, на который внешний сервис отправляет POST, является клиентом, отличным от браузера, поэтому он проходит, но если вы хотите явно:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// Protected automatically: a cross-origin page cannot POST here from a browser.
app.MapPost("/transfer", (TransferRequest req) => Results.Ok());

// Opt a single endpoint out.
app.MapPost("/webhook", (Payload p) => Results.Ok())
   .DisableAntiforgery();

app.Run();

В MVC способ обхода на уровне действия не меняется:

[HttpPost]
[IgnoreAntiforgeryToken]
public IActionResult Receive(Payload p) => Ok();

Чтобы отключить эту возможность для всего приложения, задайте ключ конфигурации DisableCsrfProtection:

{
  "DisableCsrfProtection": true
}

Если встроенная логика вердикта не подходит вашей топологии, зарегистрируйте собственную реализацию ICsrfProtection, чтобы полностью заменить решение о доверии.

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

Этот API впервые появился в Preview 4 и был переработан в Preview 6, чтобы следовать стандартным соглашениям options, поэтому, если вы пробовали его раньше, перепроверьте свою настройку. И относитесь к нему как к эшелонированной защите, а не как к замене аутентификации: он останавливает межсайтовый браузерный вектор, а не украденный bearer-токен. Полные подробности приведены в примечаниях к выпуску ASP.NET Core Preview 6. Установите SDK .NET 11 Preview 6, укажите целевую платформу net11.0 и перед публикацией проверьте каждую конечную точку, которая законно ожидает межсайтовые браузерные POST-запросы.

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.

< Назад