A limitação de taxa é essencial para proteger os recursos do aplicativo ou do site contra o uso excessivo, ou inadequado. Seja como resultado de uma intervenção humana mal-intencionada, de ataques baseados em bots ou de uma vulnerabilidade negligenciada, o uso indevido de recursos pode interferir no acesso legítimo ao seu aplicativo e introduzir vulnerabilidades graves.

Este artigo explora como adicionar limitação de taxa a uma API em um aplicativo Laravel.

Controle o tráfego da sua API no Laravel

A limitação de taxa é um mecanismo projetado para atenuar a exploração dos recursos do seu aplicativo. Embora tenha muitos usos, é particularmente útil para APIs públicas em sistemas grandes e dimensionáveis. Ele garante que todos os usuários legítimos tenham acesso justo aos recursos do sistema.

A limitação de taxa também é fundamental para a segurança, o controle de custos e a estabilidade geral do sistema. Ele pode ajudar a evitar ataques baseados em solicitações, como ataques distribuídos de negação de serviço (DDoS – distributed denial-of-service). Esse ataque se baseia no envio de solicitações repetidas para sobrecarregar e interromper o acesso a um aplicativo ou servidor de site.

Há vários métodos para implementar a limitação de taxa. Você pode usar variáveis que caracterizam o solicitante para determinar quem pode acessar seu aplicativo e com que frequência. Algumas variáveis comuns incluem:

  • Endereço IP – A implementação de limites de taxa com base em endereços IP permite que você restrinja o número de solicitações por endereço. Esse método é especialmente vantajoso em circunstâncias em que os usuários podem acessar um aplicativo sem fornecer credenciais.
  • Chave de API – Limitar o acesso por meio de chaves API implica fornecer ao solicitante, chaves API pré-geradas e estabelecer limites de taxa por chave. Com essa abordagem, você também pode aplicar diferentes níveis de acesso às chaves API geradas.
  • ID do cliente – Você também pode gerar previamente uma ID do cliente que um usuário pode incorporar no cabeçalho ou no corpo das solicitações de API. Esse método permite que você defina níveis de acesso por ID para garantir que nenhum cliente monopolize os recursos do sistema.

Middleware do Laravel

O middleware fornece um mecanismo conveniente para inspecionar e filtrar solicitações HTTP que entram em um aplicativo. Essencialmente, é uma camada de código entre o aplicativo e sua infraestrutura subjacente para permitir a comunicação entre seus recursos.

Como implementar limites de taxa

Este tutorial usa uma API de minibiblioteca existente na framework do Laravel 10 para demonstrar o uso do Laravel Throttle. O projeto inicial de amostra contém as implementações básicas de criação, leitura, atualização e exclusão (CRUD) necessárias para gerenciar livros em uma coleção e duas rotas extras para demonstrar alguns conceitos de limitação de taxa.

Pré-requisitos

O tutorial pressupõe que você esteja familiarizado com os conceitos básicos de desenvolvimento de API no Laravel. Certifique-se de que você tenha o seguinte:

Você também usa o MyKinsta para configurar e implantar essa API. Você pode acompanhar o template do projeto fornecido e visualizar o resultado no código-fonte completo.

Configuração do aplicativo Laravel

  1. Para começar, clone o template de projeto.
  2. Em seguida, crie um arquivo .env no diretório raiz do projeto e copie o conteúdo de .env.example para ele.
  3. Em seguida, conclua a configuração usando os seguintes comandos para instalar as dependências do aplicativo e gerar a chave do aplicativo.
composer install
php artisan key:generate

Se esse comando não adicionar automaticamente a chave do aplicativo ao seu arquivo .env, execute php artisan key:generate --show, copie a chave gerada e cole no arquivo .env como o valor para APP_KEY.

  1. Quando a instalação das dependências e a geração da chave do aplicativo estiverem concluídas, inicie o aplicativo usando o seguinte comando:
php artisan serve

Esse comando inicia o aplicativo e o torna acessível por meio do navegador em https://127.0.0.1:8000.

  1. Visite a URL para confirmar se a página de boas-vindas do Laravel aparecerá:
A tela de boas-vindas do Laravel
A tela de boas-vindas do Laravel

Configurações do banco de dados

Vamos configurar e definir o banco de dados do aplicativo no MyKinsta.

  1. Navegue até o painel de controle da sua conta MyKinsta e clique no botão Adicionar serviço:
Painel MyKinsta com vários serviços configurados.
Painel MyKinsta com vários serviços configurados.
  1. Na lista Adicionar serviço, clique em Banco de dados e configure os parâmetros para iniciar sua instância do banco de dados:
Configuração do banco de dados MyKinsta.
Configuração do banco de dados MyKinsta.

Este tutorial usa o MariaDB, mas você pode escolher qualquer uma das opções de banco de dados compatíveis com o Laravel que a Kinsta oferece.

  1. Quando você tiver inserido os detalhes do seu banco de dados, clique no botão Continuar para finalizar o processo.

Os bancos de dados provisionados na Kinsta têm parâmetros de conexão internos e externos. Você deve usar parâmetros de conexão interna para aplicativos hospedados na mesma conta Kinsta e parâmetros externos para conexões externas. Portanto, use as credenciais do banco de dados externo da Kinsta para seu aplicativo.

  1. Copie e atualize as credenciais .env do banco de dados do aplicativo com as credenciais externas mostradas na captura de tela abaixo:
Detalhes de configuração do banco de dados MyKinsta.
Detalhes de configuração do banco de dados MyKinsta.
DB_CONNECTION=mysql
DB_HOST=your_host_name
DB_PORT=your_port
DB_DATABASE=your_database_info
DB_USERNAME=your_username
DB_PASSWORD=your_password
  1. Após preencher as credenciais do banco de dados, teste a conexão aplicando a migração do banco de dados usando o comando abaixo:
php artisan migrate

Se tudo funcionar corretamente, você verá uma resposta semelhante à essa:

Migração bem-sucedida do banco de dados em um terminal.
Migração bem-sucedida do banco de dados em um terminal.
  1. Em seguida, use o seguinte comando para listar as rotas de aplicativos e ver as rotas já implementadas.
php artisan route:list

Agora você deve ver os endpoints de API disponíveis:

Lista de rotas do aplicativo no terminal.
Lista de rotas do aplicativo no terminal.
  1. Inicie o aplicativo e confirme se tudo continua funcionando bem. Você pode testar esses endpoints por meio do terminal usando uma ferramenta como Postman ou CURL.

Como limitar a taxa em um aplicativo Laravel

Há várias técnicas de limitação de taxa disponíveis para aplicativos Laravel. Você pode bloquear um conjunto de endereços IP ou impor limites de solicitação baseados na duração com base no endereço IP, ou no user_id de um usuário. A seguir, você aplicará cada um desses métodos.

  1. Instale o pacote Laravel Throttle usando o seguinte comando:
composer require "graham-campbell/throttle:^10.0"
  1. Você também pode fazer alterações adicionais nas configurações do Laravel Throttle publicando o arquivo vendor configurations:
php artisan vendor:publish --provider="GrahamCampbellThrottleThrottleServiceProvider"

Como bloquear endereços IP

Uma técnica de limitação de taxa permite que você bloqueie solicitações de um conjunto específico de endereços IP.

  1. Para começar, crie o middleware necessário:
php artisan make:middleware RestrictMiddleware
  1. Em seguida, abra o arquivo de middleware app/Http/Middleware/RestrictMiddleware.php criado e substitua o código na função handle pelo snippet abaixo. Certifique-se de que você adicionou use App; à lista de importações na parte superior do arquivo.
$restrictedIps = ['127.0.0.1', '102.129.158.0'];
if(in_array($request->ip(), $restrictedIps)){
  App::abort(403, 'Request forbidden');
}
return $next($request);

No arquivo app/Http/Kernel.php, crie um alias para esse aplicativo de middleware atualizando a array middlewareAliases da seguinte forma:

protected $middlewareAliases = [
. . .
'custom.restrict' => AppHttpMiddlewareRestrictMiddleware::class,
];
  1. Em seguida, aplique esse middleware ao /restricted-route no arquivo routes/api.php da seguinte forma e teste:
Route::middleware(['custom.restrict'])->group(function () {
  Route::get('/restricted-route', [BookController::class, 'getBooks']);
});

Quando está funcionando corretamente, esse middleware bloqueia todas as solicitações dos IPs na array $restrictedIps: 127.0.0.1 e 102.129.158.0. As solicitações desses IPs retornam uma resposta 403 Forbidden, conforme mostrado abaixo:

Uma resposta 403 Forbidden para o endpoint/restricted-route GET no Postman.
Uma resposta 403 Forbidden para o endpoint/restricted-route GET no Postman.

Como limitar as solicitações por endereço IP

Em seguida, você limita a taxa de solicitações usando o endereço IP do usuário.

  1. Aplique o middleware Throttle às rotas GET e PATCH do endpoint /book em routes/api.php:
Route::middleware(['throttle:minute'])->group(function () {
  Route::get('/book', [BookController::class, 'getBooks']);
});

Route::middleware(['throttle:5,1'])->group(function () {
  Route::patch('/book', [BookController::class, 'updateBook']);
});
  1. Você também deve atualizar a função configureRateLimiting no arquivo app/Providers/RouteServiceProvider com o middleware que adicionou às rotas acima.
… 
RateLimiter::for('minute', function (Request $request) {
  return Limit::perMinute(5)->by($request->ip());
});

Essa configuração limita as solicitações ao endpoint /book GET a 5 por minuto, conforme mostrado abaixo.

Uma resposta
Uma resposta “429 Too Many Requests” para o endpoint/book GET no Postman.

Como limitar com base no ID do usuário e nas sessões

  1. Para limitar a taxa usando os parâmetros user_id e session, atualize a função configureRateLimiting no arquivo app/Providers/RouteServiceProvider com os seguintes limitadores e variáveis adicionais:
...
RateLimiter::for('user', function (Request $request) {
  return Limit::perMinute(10)->by($request->user()?->id ?: $request->ip());
});
RateLimiter::for('session', function (Request $request) {
  return Limit::perMinute(15)->by($request->session()->get('key') ?: $request->ip());
});
  1. Por fim, aplique esse código às rotas /book/{id} GET e /book POST no arquivo routes/api.php:
Route::middleware(['throttle:user'])->group(function () {
  Route::get('/book/{id}', [BookController::class, 'getBook']);
});
Route::middleware(['throttle:session'])->group(function () {
  Route::post('/book', [BookController::class, 'createBook']);
});

Esse código limita as solicitações que usam user_id e session, respectivamente.

Métodos adicionais no Throttle

O Laravel Throttle apresenta vários métodos adicionais para que você tenha maior controle sobre sua implementação de limitação de taxa. Esses métodos incluem:

  • attempt – Atinge o endpoint, incrementa a contagem de ocorrências e retorna um booleano indicando se o limite de ocorrências configurado for excedido.
  • hit – Atinge o Throttle, aumenta a contagem de ocorrências e retorna $this para permitir outra chamada de método (opcional).
  • clear – Redefine a contagem do Throttle para zero e retorna $this para que você possa fazer outra chamada de método, se desejar.
  • count – Retorna o número total de ocorrências para o Throttle.
  • check – Retorna um booleano que indica se o limite de ocorrências do Throttle foi excedido.
  1. Para explorar a limitação de taxa usando esses métodos, crie um aplicativo de middleware chamado CustomMiddleware usando o comando abaixo:
php artisan make:middleware CustomMiddleware
  1. Em seguida, adicione os seguintes arquivos de importação ao arquivo de middleware recém-criado em app/Http/Middleware/CustomMiddleware.php:
use GrahamCampbellThrottleFacadesThrottle;
use App;
  1. Em seguida, substitua o conteúdo do método handle pelo seguinte trecho de código:
$throttler = Throttle::get($request, 5, 1);
Throttle::attempt($request);
if(!$throttler->check()){
  App::abort(429, 'Too many requests');
}
return $next($request);
  1. No arquivo app/Http/Kernel.php, crie um alias para esse aplicativo de middleware atualizando a array middlewareAliases da seguinte forma.
protected $middlewareAliases = [
. . .
'custom.throttle' => AppHttpMiddlewareCustomMiddleware::class, 
];
  1. Em seguida, aplique esse middleware ao /custom-route no arquivo routes/api.php:
Route::middleware(['custom.throttle'])->group(function () {
  Route::get('/custom-route', [BookController::class, 'getBooks']);
});

O middleware personalizado recém-implementado verifica se o limite de throttle foi excedido usando o método check. Se o limite for ultrapassado, ele responde com um erro 429. Caso contrário, permite que a requisição continue.

Como implantar o aplicativo no servidor Kinsta

Agora que você já explorou como implementar a limitação de taxa em um aplicativo Laravel, implemente o aplicativo no servidor Kinsta para torná-lo acessível globalmente.

  1. Comece enviando o código atualizado para o GitHub, GitLab ou Bitbucket.
  2. No painel da Kinsta, clique no botão Adicionar serviço e selecione Aplicativo na lista. Vincule sua conta Git à sua conta Kinsta e selecione o repositório correto para implantar.
  3. Em Detalhes básicos, nomeie o aplicativo e escolha o centro de dados de sua preferência. Além disso, certifique-se de que você adicionou as variáveis de ambiente do aplicativo necessárias. Elas correspondem às variáveis presentes em seu arquivo .env local: APP_KEY e as variáveis de configuração do banco de dados.
Detalhes do aplicativo no MyKinsta.
Detalhes do aplicativo no MyKinsta.
  1. Clique no botão Continuar para selecionar as variáveis do ambiente de build. Você pode deixar os valores padrão, pois a Kinsta preenche automaticamente os parâmetros necessários.
  2. Na aba Processos, você pode deixar os valores padrão ou inserir um nome para o seu processo. Você também pode selecionar os tamanhos do pod e da instância nessa guia.
  3. Finalmente, a aba Pagamento exibe um resumo de suas seleções. Adicione a opção de pagamento que você preferir para finalizar o processo.
  4. Após concluído, clique na aba Aplicativos para visualizar uma lista de aplicativos implantados.
  5. Clique no nome do aplicativo para visualizar os detalhes da implantação, conforme mostrado abaixo. Você pode usar a URL do aplicativo para acessá-lo.
Detalhes da implantação no painel MyKinsta.
Detalhes da implantação no painel MyKinsta.

Como testar o aplicativo

  1. Para testar o aplicativo localmente, use o comando php artisan serve.

Esse comando torna o navegador do aplicativo acessível em http://localhost:8000. Você pode testar os endpoints da API nos quais implementou a limitação de taxa a partir daqui, fazendo chamadas repetidas para acionar a funcionalidade de limitação de taxa.

O servidor Kinsta exibe uma resposta Access Forbidden porque você não adicionou detalhes de configuração que orientam a Kinsta sobre como servir o aplicativo. Adicione esses detalhes agora.

  1. Crie um arquivo .htaccess no diretório raiz do seu aplicativo e adicione o seguinte código ao arquivo.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
  1. Envie essas alterações para o GitHub e a Kinsta fará a implantação automática para que você faça a alteração.
  2. Agora, abra o aplicativo usando a URL fornecida e verifique se você vê a página de boas-vindas do Laravel.

Agora você pode testar os endpoints da API nos quais implementou a limitação de taxa usando o Postman, fazendo chamadas repetidas até atingir o limite configurado. Você receberá uma resposta 429 Too Many Requests após exceder o limite.

Resumo

A integração de funcionalidades de limitação de taxa em uma API do Laravel ajuda a controlar a taxa na qual os usuários consomem os recursos de um aplicativo. A limitação de taxa ajuda você a fornecer uma experiência de usuário confiável sem gastos excessivos ou insuficientes. Isso também garante que a infraestrutura subjacente do aplicativo permaneça funcional e eficiente.

Você também pode conferir o blog da Kinsta para saber mais sobre outros conceitos interessantes sobre Laravel e outras tecnologias da web. Os serviços de hospedagem acessíveis e contínuos são altamente recomendados para as necessidades do seu aplicativo e da sua equipe.

 

Marcia Ramos Kinsta

Sou o líder da equipe editorial na Kinsta. Sou um entusiasta de código aberto e adoro programar. Com mais de 7 anos de experiência em redação e edição técnica para a indústria de tecnologia, adoro colaborar com pessoas para criar conteúdos claros e concisos e melhorar fluxos de trabalho.