A validação de entrada é o processo de verificar se os dados recebidos estão de acordo com o formato, o tipo e a faixa de valores esperados antes de o aplicativo processá-los. Segundo o OWASP Input Validation Cheat Sheet (2025), a ausência de validação é a causa raiz da maioria das vulnerabilidades críticas. Verificar os dados recebidos é a primeira linha de defesa, impedindo que dados incorretos ou maliciosos entrem no sistema.
Pontos-chave
A validação de entrada é a verificação de que os dados que chegam ao aplicativo de um usuário, serviço externo ou outro componente atendem aos critérios esperados. Esses critérios incluem o tipo de dados (string, número, data), o formato (email, URL, telefone), a faixa de valores (idade de 18 a 120), o comprimento (senha de 8 a 128 caracteres) e os caracteres permitidos (apenas letras latinas, dígitos, hífen). Sem validação, o aplicativo pode processar dados que causam erros de execução, corrupção de dados ou vulnerabilidades de segurança.
A ausência de validação de entrada é a causa raiz de vulnerabilidades como SQL Injection, XSS, Command Injection, Path Traversal e Buffer Overflow. Segundo o MITRE CWE (2025), o CWE-20 (Improper Input Validation) ocupa o segundo lugar no ranking dos erros de software mais perigosos. A validação é a primeira linha de defesa no modelo de segurança Defense in Depth: ela corta os dados incorretos antes que cheguem a outros componentes do sistema.
A validação rejeita dados que não atendem aos critérios. O saneamento (limpeza) modifica os dados removendo ou escapando as partes perigosas. Por exemplo, ao inserir conteúdo HTML, a validação pode verificar o comprimento do texto e o saneamento remover as tags script usando a biblioteca HTML Purifier ou DOMPurify. O saneamento não substitui a validação: eles trabalham em conjunto. A validação é uma política de "permitido/proibido", enquanto o saneamento é "limpo antes do uso".
A validação é classificada pela profundidade da verificação. A validação de formato é a mais simples e rápida, enquanto a validação de negócios é a mais complexa e dependente de contexto. Os três níveis devem ser aplicados em sequência: primeiro o formato, depois a semântica e depois a lógica de negócios. Pular qualquer nível pode levar a um funcionamento incorreto do sistema ou a vulnerabilidades.
| Nível | O que verifica | Exemplo |
|---|---|---|
| Formato | Tipo de dados, comprimento, expressão regular | O email contém @, comprimento 5-100 |
| Semântica | Correção lógica do valor | A data de nascimento não está no futuro |
| Validação de negócios | Conformidade com as regras de negócio | O valor da transferência não excede o saldo |
Verificação do tipo de dados, tamanho, formato e caracteres permitidos. É implementada por meio de expressões regulares, tipos nativos das linguagens e bibliotecas de validação. Exemplos: verificar um UUID (formato de 8-4-4-4-12 dígitos hexadecimais), verificar um número de telefone (apenas dígitos, + no início, de 7 a 15 caracteres), verificar um inteiro (valor dentro do intervalo Integer.MIN_VALUE — Integer.MAX_VALUE). A validação de formato é o nível mínimo necessário para qualquer campo de entrada.
Verificação da correção lógica dos dados no contexto do domínio. Por exemplo: a data de início não é posterior à data de término, a idade está dentro de limites razoáveis para o sistema, as coordenadas estão dentro da área de serviço. A validação semântica exige compreensão do contexto de negócios e não pode ser feita apenas pelo formato. Exemplo: o campo "número de ingressos" pode passar na validação de formato (inteiro, > 0), mas semanticamente não pode exceder o número de assentos disponíveis.
O nível mais complexo — verificar se os dados estão em conformidade com as regras de negócio do aplicativo. Exemplos: um usuário não pode excluir o único administrador, o valor do pedido não excede o limite de crédito, um produto só pode ser pedido se estiver em estoque. A validação de negócios geralmente exige consultas ao banco de dados ou serviços externos e é realizada após as verificações de formato e semântica. Os erros de validação de negócios são a causa mais comum de insatisfação dos usuários.
A validação no cliente (no navegador ou no aplicativo móvel) é necessária para a comodidade do usuário: feedback imediato sem enviar dados ao servidor. No entanto, a validação no servidor é a única confiável, pois o código do cliente sempre pode ser contornado. Envie solicitações pelas ferramentas do desenvolvedor, Postman ou um proxy (Burp Suite) — e a validação no cliente deixa de existir. Segundo o PortSwigger Research (2025), mais de 90% dos aplicativos web testados dependem exclusivamente da validação no cliente para pelo menos um campo.
A validação no cliente pode desativar o botão de envio, destacar erros e mostrar dicas. A validação no servidor é uma verificação obrigatória de cada parâmetro, mesmo que o cliente já o tenha verificado. Duplicar a validação em ambos os níveis é uma prática padrão. O servidor deve verificar os dados como se o cliente não existisse. Isso garante proteção contra solicitações modificadas, ataques automatizados e clientes maliciosos.
Na web — atributos HTML5 (required, pattern, min/max, type="email") e JavaScript. Em aplicativos móveis — validadores nativos de campos de texto (InputFilter no Android, textField(:shouldChangeCharactersIn:) no iOS). React Hook Form e Formik para React, Vuelidate para Vue, Angular Reactive Forms — bibliotecas populares para validação no cliente. Todas suportam regras personalizadas e validação assíncrona (verificação da unicidade do login no servidor).
// Exemplo de validação no servidor com Express e Joi
const Joi = require('joi');
const userSchema = Joi.object({
email: Joi.string()
.email()
.required()
.max(255),
age: Joi.number()
.integer()
.min(18)
.max(120)
.required(),
password: Joi.string()
.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,128}$/)
.required()
});
app.post('/api/users', async (req, res) => {
const { error, value } = userSchema.validate(req.body);
if (error) {
return res.status(400).json({
error: error.details[0].message
});
}
// value — dados já validados e seguros
const user = await User.create(value);
res.status(201).json(user);
});
Os aplicativos móveis impõem requisitos especiais à validação de dados. A tela é menor — os erros devem ser concisos, o teclado contextual (numérico para digitar números) e a verificação assíncrona para não bloquear a interface. As plataformas nativas fornecem mecanismos integrados de validação que devem ser usados por padrão. As Material Design Guidelines para Android e as Human Interface Guidelines para iOS contêm recomendações detalhadas para exibir erros de validação.
O Jetpack Compose oferece uma abordagem declarativa para validação por meio do gerenciamento de estado. Cada campo de entrada está vinculado a um estado (MutableState), e o erro é calculado com base no valor atual. A biblioteca Compose Validator simplifica a criação de regras: required, email, min/max length, pattern. A validação é acionada na mudança do texto (onValueChange) ou na tentativa de envio do formulário. Recomenda-se mostrar o erro somente após o primeiro envio ou depois que o usuário terminar de digitar (debounce 300-500ms).
O SwiftUI não tem um mecanismo integrado de validação de formulários, mas permite implementá-lo facilmente por meio de Combine e property wrappers. Use @State para o valor do campo e uma propriedade calculada para o erro. O framework ValidatedPropertyKit fornece decoradores prontos: @Validated().email(), @Validated().range(18...120). Recomendação do iOS — usar os tipos de teclado (UIKeyboardType.emailAddress, .numberPad) e a capitalização automática para reduzir o número de erros no nível de entrada.
O Flutter fornece as classes Form e TextFormField com validação integrada por meio de um callback de validador. Cada campo retorna um erro como string ou null se os dados estiverem corretos. FormState.validate() executa a verificação de todos os campos do formulário. O pacote reactive_forms para casos complexos: validadores personalizados, verificação assíncrona, regras dinâmicas. O Flutter Web e a versão móvel usam a mesma API, o que simplifica a manutenção.
// Exemplo de validação de formulário em Flutter
Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email is required';
}
if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$')
.hasMatch(value)) {
return 'Enter a valid email';
}
return null;
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
// Processar dados válidos
}
},
child: Text('Enviar'),
),
],
),
)
Os frameworks modernos fornecem validadores integrados que cobrem 80% das necessidades. Os 20% restantes exigem regras personalizadas, expressões regulares ou a composição das existentes. O princípio-chave é que a validação deve ser declarativa para ser facilmente lida, testada e mantida. Evite lógica de validação espalhada por controladores e telas — mova-a para classes ou esquemas separados.
| Ferramenta | Plataforma | Características |
|---|---|---|
| Joi | Node.js | Esquemas declarativos, mensagens personalizadas |
| Pydantic | Python | Type hints, validação automática do modelo |
| Zod | TypeScript | Inferência de tipos, tipagem estrita |
| javax.validation | Java | Bean Validation, @NotNull, @Size, @Pattern |
| FluentValidation | .NET | API fluente, rulesets, regras condicionais |
White-list (lista branca) — você define quais dados são permitidos; todo o resto é rejeitado. Black-list (lista negra) — você define quais dados são proibidos; todo o resto passa. A lista branca é sempre mais confiável: você sabe exatamente quais dados passarão. A lista negra exige prever todos os ataques possíveis, o que é impossível. Exemplo: ao verificar a idade, use a lista branca (apenas números de 18 a 120), não a lista negra (proibir "0", "-1", "999999").
As expressões regulares são uma ferramenta eficaz para validação de formato, mas podem ser fonte de ataques ReDoS (Regular Expression Denial of Service). Alguns padrões (por exemplo, (a+)+b) causam retrocesso catastrófico em strings longas, carregando completamente a CPU do servidor. Use bibliotecas regex comprovadas e limite o comprimento da string antes de aplicar uma expressão regular. Para casos complexos (email, URL), use os analisadores nativos das linguagens em vez de expressões regulares caseiras.
Até desenvolvedores experientes cometem erros ao implementar a validação. Os mais comuns: validação apenas no cliente, regras excessivamente rígidas (senha "Must contain uppercase, lowercase, digit, special char, >= 12 chars, must not repeat characters"), mensagens de erro pouco informativas ("Error: invalid input") e ignorar casos limite (espaços no início/fim, caracteres Unicode, strings vazias). Cada um desses erros piora a UX e pode reduzir a conversão de formulários.
if (value) não distingue string vazia de zero, false ou "0"A melhor prática é um sistema centralizado de validação coberto por testes unitários. Cada regra deve ser testada separadamente: valores limite, dados corretos, ataques típicos (tentativas de SQLi, payloads XSS, strings muito longas). Testes de regressão na validação impedem o enfraquecimento acidental das regras durante a refatoração. Use testes baseados em propriedades (QuickCheck, fast-check) para gerar dados aleatórios e verificar se a validação não falha com exceção.
Perguntas frequentes
A validação rejeita dados incorretos, enquanto o saneamento os limpa. Por exemplo, ao inserir texto HTML, a validação verifica o comprimento máximo e o saneamento remove as tags script via DOMPurify. Ambos os processos são obrigatórios: validação para controle de formato, saneamento para segurança da saída.
Não, nunca. A validação no cliente é facilmente contornada por meio de interceptação e modificação de solicitações. Use ferramentas como Burp Suite ou simplesmente curl. A validação no servidor é a única maneira confiável de proteger o sistema. A validação no cliente serve apenas para melhorar a experiência do usuário.
Verifique o tipo MIME (não apenas a extensão), o tamanho do arquivo e a assinatura (bytes mágicos no início do arquivo) por meio da validação de assinatura de arquivo. Nunca confie na extensão — renomeie o arquivo ao salvar. Para imagens, re-encode-as com uma biblioteca de servidor (ImageMagick, Sharp), o que remove o código incorporado dos dados EXIF.
ReDoS (Regular Expression Denial of Service) é um ataque em que o invasor envia uma string especialmente construída que causa retrocesso catastrófico em uma expressão regular. Como resultado, a CPU do servidor fica 100% carregada e nenhuma resposta é gerada. Proteção: limitar o comprimento da string, timeouts de regex e usar padrões comprovados.
Sim, se os dados forem exibidos em uma WebView ou usados em contexto HTML. Se o backend for comprometido, os dados podem conter código malicioso. Valide e sane qualquer dado exibido ao usuário, independentemente da fonte. Em aplicativos móveis, isso é especialmente importante para componentes híbridos.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também