Integrar um sistema de verificação por SMS é uma das formas mais eficazes de aumentar a segurança de uma aplicação. Seja para confirmar um novo cadastro, autorizar uma transação ou implementar a autenticação de dois fatores (2FA), o processo adiciona uma camada robusta de proteção. Para desenvolvedores Python, a tarefa é direta e pode ser realizada com ferramentas nativas e bibliotecas padrão.
Este guia prático mostra como construir um fluxo de verificação por SMS em Python, desde a geração do código até a sua validação, usando uma API de SMS genérica como exemplo.
Por que usar verificação por SMS em aplicações Python?
O SMS é um canal de comunicação universal, acessível por praticamente qualquer pessoa com um telefone celular, sem a necessidade de instalar aplicativos adicionais. Em um ambiente Python, seja em um backend com Django, Flask, FastAPI ou um script simples, a verificação por SMS ajuda a:
- Confirmar a identidade do usuário: Garante que o usuário que está se cadastrando ou acessando uma conta realmente possui o número de telefone informado.
- Prevenir contas falsas e bots: A necessidade de um número de telefone válido dificulta a criação automatizada de contas em massa.
- Aumentar a segurança de transações: Adiciona uma etapa de confirmação para ações críticas, como redefinir senhas ou realizar pagamentos.
- Recuperação de conta segura: Oferece um método confiável para que os usuários recuperem o acesso às suas contas caso esqueçam a senha.
Pré-requisitos para começar
Antes de escrever o código, você precisará de alguns elementos essenciais:
- Python instalado: Este guia assume que você tem o Python 3.6 ou superior em seu ambiente.
- Biblioteca
requests: Para fazer as chamadas HTTP para a API de SMS. Instale compip install requests. - Acesso a uma API de SMS: Você precisará de uma plataforma como a SMS VOLT, que forneça uma API para o envio de mensagens. Geralmente, isso envolve obter uma chave de API (API Key) e a URL do endpoint.
- Um número de telefone para testes: Para receber os códigos de verificação durante o desenvolvimento.
O fluxo de verificação por SMS: passo a passo
O processo lógico para verificar um usuário via SMS pode ser dividido em três etapas principais, que se traduzem em funções ou métodos no seu código Python:
- Geração do Código: O sistema gera um código OTP (One-Time Password) numérico, aleatório e de curta duração.
- Envio do SMS: O sistema utiliza uma API de SMS para enviar o código gerado para o número de telefone do usuário.
- Validação do Código: O usuário insere o código recebido na sua aplicação. O sistema então compara o código inserido com o que foi originalmente gerado e armazenado temporariamente.
Vamos detalhar cada passo com exemplos de código.
Passo 1: Gerando um código OTP seguro em Python
O primeiro passo é gerar um código seguro. Usar funções simples como random.randint() pode não ser ideal por questões de previsibilidade. A biblioteca secrets, incluída no Python, é a mais indicada para gerar dados criptograficamente seguros.
Vamos criar uma função que gera um código de 6 dígitos:
import secrets
def gerar_otp(tamanho=6):
"""Gera um código OTP numérico criptograficamente seguro."""
if not isinstance(tamanho, int) or tamanho <= 0:
raise ValueError("O tamanho deve ser um inteiro positivo.")
range_start = 10**(tamanho - 1)
range_end = (10**tamanho) - 1
# secrets.randbelow é preferível a random.randint para segurança
numero_aleatorio = secrets.randbelow(range_end - range_start + 1) + range_start
# Formata como string com zeros à esquerda, se necessário
return str(numero_aleatorio).zfill(tamanho)
# Exemplo de uso
codigo_gerado = gerar_otp()
print(f"Código OTP gerado: {codigo_gerado}")
Passo 2: Enviando o SMS com a API (usando requests)
Com o código em mãos, o próximo passo é enviá-lo. A maioria das APIs de SMS funciona com uma requisição HTTP POST para um endpoint específico, enviando a chave da API, o número de destino e a mensagem.
Vamos simular uma função que envia o SMS. Substitua 'SUA_API_KEY', 'URL_DA_API_DE_SMS' e a estrutura do payload pelos valores reais do seu provedor.
import requests
def enviar_sms_verificacao(numero_destino, codigo_otp):
"""Envia um SMS de verificação usando uma API externa."""
API_KEY = 'SUA_API_KEY'
API_ENDPOINT = 'https://api.seuservico.com/send'
mensagem = f"Seu código de verificação é: {codigo_otp}"
# O formato do payload varia entre provedores de API
payload = {
'api_key': API_KEY,
'to': numero_destino, # Formato E.164 é recomendado: +55119XXXXXXXX
'message': mensagem
}
try:
response = requests.post(API_ENDPOINT, json=payload, timeout=10)
response.raise_for_status() # Lança uma exceção para erros HTTP (4xx ou 5xx)
print(f"SMS enviado para {numero_destino}. Status: {response.status_code}")
# Em produção, analise a resposta da API para confirmar a entrega
return True, response.json()
except requests.exceptions.RequestException as e:
print(f"Erro ao enviar SMS: {e}")
# Adicione lógica de log ou tratamento de erro aqui
return False, str(e)
# Exemplo de uso
numero_usuario = '+5511987654321'
sucesso, resposta = enviar_sms_verificacao(numero_usuario, codigo_gerado)
É fundamental validar o formato do número de telefone antes de enviá-lo à API, preferencialmente usando o padrão E.164.
Passo 3: Validando o código OTP fornecido pelo usuário
Finalmente, o usuário digita o código recebido em um formulário na sua aplicação. Seu backend Python precisa receber esse código e compará-lo com o valor original que você armazenou.
Nesta etapa, você também deve verificar se o código não expirou.
import datetime
# Suponha que você armazenou o código e o tempo de geração assim:
# otp_storage = {
# 'numero_telefone': '+5511987654321',
# 'codigo': '123456',
# 'timestamp': datetime.datetime.utcnow()
# }
def validar_otp(codigo_usuario, codigo_armazenado, timestamp_geracao, validade_segundos=300):
"""Valida o código OTP e seu tempo de expiração."""
tempo_agora = datetime.datetime.utcnow()
tempo_decorrido = (tempo_agora - timestamp_geracao).total_seconds()
if tempo_decorrido > validade_segundos:
print("Código OTP expirou.")
return False
# Usar secrets.compare_digest para prevenir ataques de tempo (timing attacks)
if secrets.compare_digest(codigo_usuario, codigo_armazenado):
print("Código OTP válido!")
return True
else:
print("Código OTP inválido.")
return False
# Exemplo de uso
# Supondo que 'otp_storage' foi preenchido antes
# codigo_do_form = input("Digite o código recebido: ")
# is_valid = validar_otp(
# codigo_do_form,
# otp_storage['codigo'],
# otp_storage['timestamp']
# )
Boas práticas e considerações de segurança
Ao integrar a verificação por SMS no seu app, algumas práticas são cruciais para a robustez e segurança do sistema:
- Limite de tempo: Sempre defina um tempo de expiração curto para os códigos OTP (3 a 10 minutos é um padrão comum).
- Limite de tentativas: Implemente um limite de tentativas de validação (ex: 3 a 5 tentativas) para um mesmo código, prevenindo ataques de força bruta.
- Rate Limiting: Limite a frequência com que um usuário pode solicitar o envio de um novo código para o mesmo número. Isso evita abusos e custos desnecessários com a API.
- Use
secrets.compare_digest: Para comparar strings sensíveis como códigos e senhas, essa função é mais segura que o operador==. - Não exponha informações: As mensagens de erro devem ser genéricas. Em vez de "código expirado" ou "código incorreto", use uma mensagem única como "O código de verificação é inválido ou expirou".
Perguntas frequentes
Preciso de uma biblioteca específica para SMS em Python?
Não necessariamente. A maioria dos serviços de API de SMS modernos é baseada em REST e pode ser consumida facilmente com a biblioteca requests, que é o padrão de fato para requisições HTTP em Python. Algumas plataformas podem oferecer um SDK em Python, o que pode simplificar a integração, mas não é um requisito.
Como lidar com códigos OTP que expiram?
Sua lógica de validação deve sempre verificar o timestamp de geração do código. Se o tempo atual ultrapassar o tempo de geração mais o período de validade (ex: 5 minutos), o código deve ser considerado inválido, mesmo que corresponda ao valor armazenado. O usuário deve então ser instruído a solicitar um novo código.
E se o SMS não chegar ao usuário?
Falhas na entrega podem ocorrer por diversos motivos, como problemas na operadora ou filtros antispam. Sua interface deve ter um botão de "Reenviar código", sujeito a um temporizador para evitar múltiplos envios imediatos. Além disso, é importante monitorar as respostas da sua API de SMS para identificar falhas de entrega.
É seguro armazenar o código OTP no banco de dados?
Sim, desde que seja uma solução temporária. Armazene o código OTP junto com um timestamp de criação e um indicador de qual usuário/número ele pertence. Após a validação bem-sucedida ou a expiração do código, ele deve ser invalidado ou removido para que não possa ser reutilizado.


![Como Integrar Verificação por SMS no Seu App [Guia Prático]](/blog/covers/integrar-verificacao-sms-no-seu-app.jpg)
