ASP.NET Core의 요청 압축 해제

작성자: David Acker

요청 압축 해제 미들웨어:

  • API 엔드포인트가 압축된 콘텐츠로 요청을 수락할 수 있도록 합니다.
  • Content-Encoding HTTP 헤더를 사용하여 압축된 콘텐츠를 포함하는 요청을 자동으로 식별하고 압축을 해제합니다.
  • 압축된 요청을 처리하는 코드를 작성할 필요가 없습니다.

요청의 Content-Encoding 헤더 값이 사용 가능한 압축 해제 공급자 중 하나와 일치하는 경우 미들웨어는 다음을 수행합니다.

  • 일치하는 공급자를 사용하여 적절한 압축 해제 스트림에서 HttpRequest.Body를 래핑합니다.
  • 요청 본문이 더 이상 압축되지 않음을 나타내는 Content-Encoding 헤더를 제거합니다.

Content-Encoding 헤더를 포함하지 않는 요청은 요청 압축 해제 미들웨어에서 무시됩니다.

압축 해제:

  • 요청 본문을 읽을 때 발생합니다. 즉, 압축 해제는 모델 바인딩의 엔드포인트에서 발생합니다. 요청 본문은 열심히 압축 해제되지 않습니다.
  • 지정된 Content-Encoding데이터에 대해 잘못된 압축 데이터를 사용하여 압축 해제된 요청 본문을 읽으려고 하면 예외가 throw됩니다. Brotli는 throw System.InvalidOperationException할 수 있습니다. Decoder ran into invalid data. Deflate 및 GZip은 다음을 throw System.IO.InvalidDataException할 수 있습니다. The archive entry was compressed using an unsupported compression method.

미들웨어가 압축된 콘텐츠가 포함된 요청을 발견했지만 압축을 해제할 수 없는 경우 요청은 파이프라인의 다음 대리자에게 전달됩니다. 예를 들어 지원 Content-Encoding 되지 않는 헤더 값 또는 여러 Content-Encoding 헤더 값이 있는 요청은 파이프라인의 다음 대리자에게 전달됩니다.

구성

다음 코드는 기본Content-Encoding 형식에 대한 요청 압축 해제를 사용하고 AddRequestDecompression(IServiceCollection)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 헤더 값 설명
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이 throw됩니다.

우선 순위에 따라 엔드포인트의 최대 요청 크기는 다음을 기준으로 설정됩니다.

  1. IRequestSizeLimitMetadata.MaxRequestBodySize(예: MVC 엔드포인트의 경우 RequestSizeLimitAttribute 또는 DisableRequestSizeLimitAttribute)
  2. 전역 서버 크기 제한 IHttpMaxRequestBodySizeFeature.MaxRequestBodySize. MaxRequestBodySizeIHttpMaxRequestBodySizeFeature.MaxRequestBodySize를 사용하여 요청별로 재정의할 수 있지만 기본적으로 웹 서버 구현에 대해 구성된 제한이 적용됩니다.
웹 서버 구현 MaxRequestBodySize 구성
HTTP.sys HttpSysOptions.MaxRequestBodySize
IIS IISServerOptions.MaxRequestBodySize
Kestrel KestrelServerLimits.MaxRequestBodySize

Warning

요청 본문 크기 제한을 사용하지 않도록 설정하면 특히 요청 본문이 버퍼링되는 경우 제어되지 않는 리소스 사용과 관련하여 보안 위험이 발생합니다. DoS(denial-of-service) 공격의 위험을 완화하기 위한 안전 장치가 마련되어 있는지 확인합니다.

추가 리소스