Распаковка запросов в 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
, которые по умолчанию поддерживает ПО промежуточного слоя распаковки запросов, перечислены в следующей таблице:
Значения заголовков Content-Encoding |
Description |
---|---|
br |
Формат сжатых данных Brotli |
deflate |
Формат сжатых данных Deflate |
gzip |
Формат файлов gzip |
Настраиваемые поставщики распаковки
Поддержку пользовательских кодировок можно добавлять, создавая настраиваемые классы поставщиков распаковки, реализующие 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, чтобы предотвратить чтение дополнительных байтов из потока.
Максимальный размер запроса для конечной точки задается в порядке приоритета следующим образом:
- IRequestSizeLimitMetadata.MaxRequestBodySize, например RequestSizeLimitAttribute или DisableRequestSizeLimitAttribute для конечных точек MVC.
- Глобальное серверное ограничение размера — IHttpMaxRequestBodySizeFeature.MaxRequestBodySize.
MaxRequestBodySize
можно переопределить для каждого запроса, используя свойство IHttpMaxRequestBodySizeFeature.MaxRequestBodySize, но по умолчанию применяется ограничение, настроенное для реализации веб-сервера.
Реализация веб-сервера | MaxRequestBodySize Конфигурация |
---|---|
HTTP.sys | HttpSysOptions.MaxRequestBodySize |
IIS | IISServerOptions.MaxRequestBodySize |
Kestrel | KestrelServerLimits.MaxRequestBodySize |
Предупреждение
Отключение лимита для размера текста запроса создает риск для безопасности, связанный с неконтролируемым потреблением ресурсов, особенно если текст запроса буферизуется. Убедитесь, что приняты меры по безопасности, чтобы снизить риск атак типа отказ в обслуживании (DoS).
Дополнительные ресурсы
ASP.NET Core