Pular para conteúdo

Rate Limiting

Controle de taxa de requisicoes do TepConfina para protecao contra abuso.

Visao Geral

O sistema implementa rate limiting em duas camadas para proteger a API contra uso excessivo e ataques de forca bruta.

flowchart LR
    A[Requisicao] --> B{Rate Limit}
    B -->|Dentro do limite| C[Processar]
    B -->|Excedeu limite| D[429 Too Many Requests]
    D --> E[Retry-After header]

Politicas Configuradas

Politica Global

Aplicada a todos os endpoints da API.

Configuracao Valor
Limite 100 requisicoes
Janela 1 minuto
Tipo de janela Sliding Window
Identificador IP do cliente

Politica de Autenticacao

Aplicada especificamente aos endpoints de autenticacao (/api/auth/*).

Configuracao Valor
Limite 10 requisicoes
Janela 1 minuto
Tipo de janela Fixed Window
Identificador IP do cliente

Protecao contra forca bruta

O limite mais restritivo nos endpoints de autenticacao previne ataques de forca bruta contra senhas de usuarios.

Implementacao

Configuracao no Program.cs

builder.Services.AddRateLimiter(options =>
{
    // Politica global
    options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(
        context => RateLimitPartition.GetSlidingWindowLimiter(
            partitionKey: context.Connection.RemoteIpAddress?.ToString() ?? "unknown",
            factory: _ => new SlidingWindowRateLimiterOptions
            {
                PermitLimit = 100,
                Window = TimeSpan.FromMinutes(1),
                SegmentsPerWindow = 4
            }));

    // Politica de autenticacao
    options.AddFixedWindowLimiter("auth", opt =>
    {
        opt.PermitLimit = 10;
        opt.Window = TimeSpan.FromMinutes(1);
    });

    options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
});

Aplicacao nos Controllers

[ApiController]
[Route("api/[controller]")]
[EnableRateLimiting("auth")]
public class AuthController : ControllerBase
{
    [HttpPost("login")]
    public async Task<IActionResult> Login(LoginRequest request) { }

    [HttpPost("refresh")]
    public async Task<IActionResult> Refresh(RefreshRequest request) { }
}

Resposta de Limite Excedido

Quando o limite e excedido, a API retorna:

HTTP Response

HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json

{
  "title": "Too Many Requests",
  "status": 429,
  "detail": "Limite de requisicoes excedido. Tente novamente apos o periodo indicado."
}

Headers de Resposta

Header Descricao
Retry-After Segundos ate o proximo periodo disponivel
X-RateLimit-Limit Limite total de requisicoes na janela
X-RateLimit-Remaining Requisicoes restantes na janela atual
X-RateLimit-Reset Timestamp de quando a janela reseta

Tipos de Janela

Sliding Window (Global)

A janela deslizante oferece uma experiencia mais suave, pois o limite e distribuido ao longo do tempo:

Tempo:    |----seg1----|----seg2----|----seg3----|----seg4----|
Limite:   25 req/seg   25 req/seg   25 req/seg   25 req/seg
Total:    100 requisicoes por minuto (janela deslizante)

Fixed Window (Autenticacao)

A janela fixa reseta o contador a cada intervalo completo:

Tempo:    |--------1 minuto--------|--------1 minuto--------|
Limite:   10 requisicoes           10 requisicoes
Reset:    Contador volta a zero    Contador volta a zero

Tratamento no Frontend

O frontend trata automaticamente respostas 429:

api.interceptors.response.use(
  (response) => response,
  async (error) => {
    if (error.response?.status === 429) {
      const retryAfter = error.response.headers['retry-after'] || 30;
      await delay(retryAfter * 1000);
      return api.request(error.config);
    }
    return Promise.reject(error);
  }
);

Boas praticas para clientes

  • Implemente backoff exponencial ao receber 429
  • Respeite o header Retry-After
  • Evite fazer requisicoes desnecessarias (use cache local)
  • Agrupe operacoes quando possivel