Ужесточаем Десериализацию JSON в System.Text.Json. Окончание
Начало
Строгий режим и генераторы кода
В генераторах кода нужно вручную настроить все параметры в JsonSourceGenerationOptionsAttribute:
[JsonSourceGenerationOptions(
AllowDuplicateProperties = false,
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,
PropertyNameCaseInsensitive = false,
RespectNullableAnnotations = true,
RespectRequiredConstructorParameters = true
)]
Сокращенного обозначения параметра Strict не существует. Каждое свойство устанавливается индивидуально.
Строгий режим в минимальных API ASP.NET Core
В веб-приложении параметры JSON настраиваются один раз, и каждая конечная точка наследует их:
builder.Services.ConfigureHttpJsonOptions(o =>
{
o.SerializerOptions.AllowDuplicateProperties = false;
o.SerializerOptions.UnmappedMemberHandling =
JsonUnmappedMemberHandling.Disallow;
o.SerializerOptions.PropertyNameCaseInsensitive = false;
o.SerializerOptions.RespectNullableAnnotations = true;
o.SerializerOptions.RespectRequiredConstructorParameters = true;
});
// …
var app = builder.Build();
app.MapPost("/payments", (Payment pmt) =>
{
// Если тело запроса нарушает какое-либо
// из требований сериализатора, фреймворк
// вернёт 400 Bad Request без выполнения тела метода
return Results.Ok(pmt);
});
app.Run();
Фреймворк перехватывает исключение JsonException во время привязки модели и возвращает ошибку 400 Bad Request с подробным описанием проблемы. Ваш код конечной точки видит только действительные, полностью привязанные объекты.
Параметры для каждой конечной точки
Если требуется строгая проверка для одних конечных точек, но более мягкий анализ для других, используйте Results.Json с явными параметрами:
app.MapGet("/api/data", () =>
Results.Json(new { message = "Hello" }, JsonSerializerOptions.Strict));Для десериализации можно брать чистое тело запроса:
app.MapPost("/api/strict",
async (HttpContext context) =>
{
var pmt = await context.Request
.ReadFromJsonAsync<Payment>(JsonSerializerOptions.Strict);
return Results.Ok(pmt);
});Когда использовать Strict
На границах доверия. Конечные точки токенов, контроллеры API — всё, где вы принимаете JSON от клиента, которого вы не полностью контролируете. Цена — исключение JsonException, когда полезная нагрузка не соответствует вашему контракту.
Если вы получаете JSON от сторонних API с несогласованными схемами, строгий режим отклонит данные, которые вы, возможно, захотите обработать корректно. В таких случаях используйте режим Default или Web и проверяйте после десериализации.
Не нужно сразу переводить всё на строгий режим. Начните с наиболее рискованных конечных точек. Перехватывайте исключения JsonException, регистрируйте их, исправляйте вызывающие стороны, отправляющие несоответствующие данные.
Параметр Strict проверяет структурные нарушения контракта. Он не защищает от глубоко вложенного JSON (используйте MaxDepth), слишком больших объёмов данных (обрабатывайте на уровне HTTP с ограничениями размера запроса) или путаницы полиморфных типов. Строгий режим — это один уровень защиты, а не единственный.
Укрепление вашей безопасности
Каждая конечная точка API, принимающая JSON, является границей доверия. Разрешительная десериализация делает эту границу уязвимой. Режим Strict не добавляет новую логику проверки. Он активирует защиту, которая уже существует в System.Text.Json, но отключена по умолчанию для обратной совместимости.
Источник: https://duendesoftware.com/blog/20260430-harden-your-dotnet-json-deserialization