Начните работу с ПО промежуточного слоя для ограничения скорости в ASP.NET Core 7

автор vadim


Ограничение скорости — это метод, используемый для ограничения количества запросов, разрешенных к определенному ресурсу, для предотвращения DDoS-атак и злоупотреблений API. После достижения порога ограничения скорости последующие запросы к ресурсу запрещаются, задерживаются или регулируются.

До .NET 7 для реализации ограничения скорости в приложениях ASP.NET Core требовалось использование сторонних пакетов, таких как AspNetCoreRateLimit. Но в ASP.NET Core 7 ограничение скорости теперь является встроенной функцией, доступной в виде промежуточного программного обеспечения, предназначенного для предотвращения злоупотреблений, защиты от атак и обеспечения справедливого распределения ресурсов.

Я обсуждал, как использовать AspNetCoreRateLimit для реализации ограничения скорости в более ранних версиях ASP.NET Core, в предыдущей статье. В этой статье мы рассмотрим, как использовать новое встроенное ПО промежуточного слоя для ограничения скорости в ASP.NET Core 7.

Чтобы использовать примеры кода, представленные в этой статье, в вашей системе должна быть установлена ​​Visual Studio 2022. Если у вас еще нет копии, вы можете скачать Visual Studio 2022 здесь.

Создайте проект веб-API ASP.NET Core 7 в Visual Studio 2022.

Прежде всего, давайте создадим проект ASP.NET Core 7 в Visual Studio 2022. Выполните следующие действия:

  1. Запустите интегрированную среду разработки Visual Studio 2022.
  2. Нажмите «Создать новый проект».
  3. В окне «Создать новый проект» выберите «ASP.NET Core Web API» из списка отображаемых шаблонов.
  4. Нажмите “Далее.
  5. В окне «Настроить новый проект» укажите имя и расположение нового проекта.
  6. При желании установите флажок «Поместить решение и проект в один каталог», в зависимости от ваших предпочтений.
  7. Нажмите “Далее.
  8. В окне «Дополнительная информация», показанном далее, оставьте флажок «Использовать контроллеры (снимите флажок, чтобы использовать минимальные API)», поскольку мы не будем использовать минимальные API в этом проекте. Оставьте для параметра «Тип аутентификации» значение «Нет» (по умолчанию).
  9. Убедитесь, что флажки «Включить поддержку Open API», «Настроить для HTTPS» и «Включить Docker» не отмечены, так как мы не будем использовать эти функции здесь.
  10. Щелкните Создать.

Мы будем использовать этот проект веб-API ASP.NET Core 7 для работы со встроенным ПО промежуточного слоя для ограничения скорости в следующих разделах.

Встроенное ограничение скорости в ASP.NET Core 7

Ограничение скорости в ASP.NET Core 7 доступно как часть пространства имен System.Threading.RateLimiting. Основным типом является абстрактный базовый класс RateLimiter, обладающий несколькими замечательными свойствами.

RateLimiter можно настроить с помощью нескольких параметров, включая максимально допустимое количество запросов, код состояния ответа и временное окно. Вы можете определить ограничение скорости в зависимости от метода HTTP, IP-адреса клиента и других факторов. У вас даже есть возможность ставить запросы в очередь вместо их отклонения.

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

  • Фиксированное окно
  • Раздвижное окно
  • Сегмент токенов
  • параллелизм

Чтобы добавить ПО промежуточного слоя для ограничения скорости в приложение ASP.NET Core 7, вы должны сначала добавить необходимые службы в контейнер, как показано во фрагменте кода, приведенном ниже.

builder.Services.AddRateLimiter(options =>
{
    //Write your code to configure the middleware here
});

Чтобы добавить промежуточное ПО в конвейер, вы должны вызвать метод расширения UseRateLimiter, как показано ниже.

app.UseRateLimiter();

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

Теперь напишите следующий код в файле Program.cs, чтобы настроить ограничитель скорости.

builder.Services.AddRateLimiter(options =>
{
    options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
    {
        return RateLimitPartition.GetFixedWindowLimiter(partitionKey: httpContext.Request.Headers.Host.ToString(), partition =>
            new FixedWindowRateLimiterOptions
            {
                PermitLimit = 5,
                AutoReplenishment = true,
                Window = TimeSpan.FromSeconds(10)
            });
    });
});

Вызов метода AddRateLimiter регистрирует ПО промежуточного слоя в коллекции служб. В этом примере используется GlobalLimiter для всех запросов, и для этого GlobalLimiter установлено значение PartitionedRateLimiter.

Затем FixedWindowLimiter используется для пополнения разрешенных запросов. Обратите внимание, что когда вы запускаете приложение и вызываете конечную точку с превышением допустимого предела, будет возвращен код состояния HTTP 503 «Служба недоступна».

Кроме того, вы можете настроить промежуточное ПО для возврата кода состояния HTTP 429 «Слишком много запросов». Для этого используйте следующий фрагмент кода.

options.OnRejected = async (context, token) =>
{
    context.HttpContext.Response.StatusCode = 429;
    await Task.CompletedTask;
};

Если вы хотите настроить сообщение об ошибке, вы можете вместо этого использовать следующий фрагмент кода.

options.OnRejected = async (context, token) =>
{
   context.HttpContext.Response.StatusCode = 429;
   await Task.CompletedTask;
};

Полный пример ограничения скорости (источник Program.cs)

Вот полный исходный код файла Program.cs для справки.

using System.Threading.RateLimiting;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
builder.Services.AddRateLimiter(options =>
{
    options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
    {
        return RateLimitPartition.GetFixedWindowLimiter(partitionKey: httpContext.Request.Headers.Host.ToString(), partition =>
            new FixedWindowRateLimiterOptions
            {
                PermitLimit = 5,
                AutoReplenishment = true,
                Window = TimeSpan.FromSeconds(10)
            });
    });
    options.OnRejected = async (context, token) =>
    {
        context.HttpContext.Response.StatusCode = 429;
        await context.HttpContext.Response.WriteAsync("Too many requests. Please try later again... ", cancellationToken: token);
    };
});
var app = builder.Build();
app.UseRateLimiter();
// Configure the HTTP request pipeline.
app.UseAuthorization();
app.MapControllers();
app.Run();

Ставьте запросы в очередь вместо того, чтобы отклонять их

Вы также можете ставить запросы в очередь вместо того, чтобы отклонять их. Чтобы добиться этого, вы должны воспользоваться свойством QueueLimit и установить желаемое значение, как показано во фрагменте кода, приведенном ниже.

builder.Services.AddRateLimiter(options =>
{
    options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
    {
        return RateLimitPartition.GetFixedWindowLimiter(partitionKey: httpContext.Request.Headers.Host.ToString(), partition =>
            new FixedWindowRateLimiterOptions
            {
                PermitLimit = 5,
                AutoReplenishment = true,
                QueueLimit = 5,
                QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
                Window = TimeSpan.FromSeconds(10)
            });
    });
    options.OnRejected = async (context, token) =>
    {
        context.HttpContext.Response.StatusCode = 429;
        await context.HttpContext.Response.WriteAsync("Too many requests. Please try later again... ", cancellationToken: token);
    };
});

Обратите внимание, что для QueueProcessingOrder установлено значение OldestFirst. Если вместо этого вы хотите, чтобы последние вставленные элементы в очереди обрабатывались первыми, вы можете установить для QueueProcessingOrder значение NewestFirst.

Используя ограничение скорости, вы можете снизить нагрузку на свой сервер и защитить его от злоумышленников, обеспечив доступность вашего сервиса и добросовестное использование доступных ресурсов. В будущих сообщениях об ограничении скорости я расскажу о различных алгоритмах ограничения скорости, доступных в ASP.NET Core 7, и о том, как мы можем реализовать настраиваемые политики ограничения скорости.

Related Posts

Оставить комментарий