Прочитать на английском

Поделиться через


Распаковка запросов в ASP.NET Core

Примечание

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 9 этой статьи.

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

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 9 этой статьи.

Важно!

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 9 этой статьи.

Автор: Дэвид Эйкер (David Acker)

ПО промежуточного слоя для распаковки запросов предоставляет такие преимущества:

  • позволяет конечным точкам API принимать запросы со сжатым содержимым;
  • использует заголовок HTTP Content-Encoding, чтобы автоматически обнаруживать и распаковывать запросы, содержащие сжатое содержимое;
  • устраняет необходимость писать код для обработки сжатых запросов.

Если значение заголовка Content-Encoding в запросе соответствует одному из доступных поставщиков распаковки, ПО промежуточного слоя:

  • использует этот поставщик для переноса HttpRequest.Body в подходящий поток распаковки;
  • удаляет заголовок Content-Encoding, так как текст запроса больше не сжат.

ПО промежуточного слоя для распаковки игнорирует запросы, не содержащие заголовок Content-Encoding.

Распаковка:

  • Происходит при чтении текста запроса. Это значит, что при привязке модели распаковка осуществляется в конечной точке. Текст запроса не декомпрессируется с нетерпением.
  • При попытке считывать декомпрессованный текст запроса с недопустимыми сжатыми данными для указанного Content-Encoding, создается исключение. Brotli может бросать System.InvalidOperationException: Decoder ran into invalid data. Deflate и GZip могут бросать System.IO.InvalidDataException: The archive entry was compressed using an unsupported compression method.

Если ПО промежуточного слоя обнаруживает запрос со сжатым содержимым, но его не удается распаковать, запрос передается следующему делегату в конвейере. Например, запрос со значением неподдерживаемого Content-Encoding заголовка или несколькими Content-Encoding значениями заголовков передается следующему делегату в конвейере.

Настройка

Следующий код использует AddRequestDecompression(IServiceCollection) и включает распаковку запроса для типов по умолчаниюContent-Encoding:UseRequestDecompression

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRequestDecompression();

var app = builder.Build();

app.UseRequestDecompression();

app.MapPost("/", (HttpRequest request) => Results.Stream(request.Body));

app.Run();

Поставщики распаковки по умолчанию

Значения заголовков Content-Encoding, которые по умолчанию поддерживает ПО промежуточного слоя распаковки запросов, перечислены в следующей таблице:

Настраиваемые поставщики распаковки

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

public class CustomDecompressionProvider : IDecompressionProvider
{
    public Stream GetDecompressionStream(Stream stream)
    {
        // Perform custom decompression logic here
        return stream;
    }
}

Настраиваемые поставщики распаковки регистрируются с использованием RequestDecompressionOptions вместе с соответствующими значениями заголовков Content-Encoding:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRequestDecompression(options =>
{
    options.DecompressionProviders.Add("custom", new CustomDecompressionProvider());
});

var app = builder.Build();

app.UseRequestDecompression();

app.MapPost("/", (HttpRequest request) => Results.Stream(request.Body));

app.Run();

Предельный размер запросов

Чтобы защититься от zip-бомб или декомпрессийных бомб:

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

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

  1. IRequestSizeLimitMetadata.MaxRequestBodySize, например RequestSizeLimitAttribute или DisableRequestSizeLimitAttribute для конечных точек MVC.
  2. Глобальное серверное ограничение размера — IHttpMaxRequestBodySizeFeature.MaxRequestBodySize. MaxRequestBodySize можно переопределить для каждого запроса, используя свойство IHttpMaxRequestBodySizeFeature.MaxRequestBodySize, но по умолчанию применяется ограничение, настроенное для реализации веб-сервера.
Реализация веб-сервера MaxRequestBodySizeКонфигурация
HTTP.sys HttpSysOptions.MaxRequestBodySize
IIS IISServerOptions.MaxRequestBodySize
Kestrel KestrelServerLimits.MaxRequestBodySize

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

Отключение лимита для размера текста запроса создает риск для безопасности, связанный с неконтролируемым потреблением ресурсов, особенно если текст запроса буферизуется. Убедитесь, что приняты меры по безопасности, чтобы снизить риск атак типа отказ в обслуживании (DoS).

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


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

Обучение

Модуль

Настройка поведения ASP.NET Core с помощью ПО промежуточного слоя - Training

Изучите и реализуйте ПО промежуточного слоя в приложении ASP.NET Core. Используйте включаемые ПО промежуточного слоя, такие как ведение журнала HTTP и проверка подлинности. Создание пользовательского ПО промежуточного слоя для обработки запросов и ответов.