Segurança em aplicações web não é um feature que você liga no fim — é um conjunto de práticas que atravessam o código todo: como você guarda senha, como autentica usuário, como autoriza ação, como criptografa dado em trânsito, e como evita os erros clássicos que um atacante usa pra entrar. Esta visão geral mostra os conceitos-base que aparecem em qualquer aplicação séria.
Toda discussão de segurança da informação gira em torno de três objetivos:
| Pilar | O que protege | Exemplo de quebra |
|---|---|---|
| Confidencialidade | Só quem tem direito vê o dado | Vazamento de senha em log |
| Integridade | O dado não foi alterado por quem não devia | Atacante muda valor de transação no meio do caminho |
| Disponibilidade | O sistema responde quando precisa | Ataque DDoS derruba o site |
Quando alguém pergunta "esse sistema é seguro?", a resposta começa com "seguro pra qual pilar?". Um banco prioriza integridade. Um chat prioriza confidencialidade. Um e-commerce prioriza disponibilidade no Black Friday.
Dois conceitos que parecem iguais mas resolvem problemas diferentes:
| Autenticação | Autorização | |
|---|---|---|
| Pergunta | "Quem é você?" | "O que você pode fazer?" |
| Vem antes ou depois | Antes | Depois (já sabe quem é) |
| Mecanismos | Senha, biometria, token, JWT, OAuth | Roles, permissions, ACL, policy |
| Erro típico | HTTP 401 (Unauthorized) | HTTP 403 (Forbidden) |
Os códigos HTTP confundem: 401 deveria significar "você é desconhecido" e 403 "te conheço mas você não pode". Na prática, autenticação primeiro, autorização depois.
Senha de usuário NUNCA é guardada em texto claro. NUNCA é guardada com hash rápido (MD5, SHA-1, SHA-256). O motivo: hash rápido pode ser quebrado por força bruta com GPU em segundos.
O que se usa é uma função de hash lenta de propósito, com salt:
O salt é um valor aleatório por usuário, guardado junto com o hash. Sem salt, dois usuários com a mesma senha teriam hashes iguais — e tabelas pré-computadas (rainbow tables) quebrariam tudo.
// ERRADO - hash rápido + sem salt
String hash = md5(senha);
// CERTO - bcrypt cuida de salt e custo
String hash = BCrypt.hashpw(senha, BCrypt.gensalt(12));
HTTP puro envia tudo em texto claro pela rede. Qualquer um no caminho (Wi-Fi público, provedor, atacante na rede local) consegue ler senha, cookie, mensagem.
HTTPS envolve o HTTP num lacre criptográfico (TLS — Transport Layer Security). O servidor apresenta um certificado, o cliente confere se é confiável, e os dois trocam chaves pra criptografar tudo dali em diante.
Cuidado com certificado expirado, auto-assinado, ou cadeia incompleta — o navegador bloqueia e o usuário entra em pânico.
A OWASP (Open Worldwide Application Security Project) publica a cada poucos anos a lista dos 10 erros de segurança mais comuns em apps web. É leitura obrigatória pra dev backend.
| # | Categoria | Exemplo concreto |
|---|---|---|
| A01 | Quebra de controle de acesso | Usuário comum acessa rota de admin |
| A02 | Falhas criptográficas | Senha em MD5, dado em texto claro |
| A03 | Injeção (SQL, comando, LDAP) | Input do usuário concatenado direto na query |
| A04 | Design inseguro | Esquecer rate-limit em endpoint de login |
| A05 | Configuração errada | Painel admin exposto na internet, S3 público |
| A06 | Componente vulnerável | Lib desatualizada com CVE conhecido (Log4Shell) |
| A07 | Falha de autenticação | Sessão sem expiração, senha "123456" aceita |
| A08 | Falha de integridade de software | CI/CD que aceita código de qualquer fonte |
| A09 | Falha de log e monitoramento | Sem alerta quando 1000 logins falham seguidos |
| A10 | SSRF | Servidor faz request pra URL escolhida pelo usuário |
A maioria dos vazamentos famosos cai num desses 10. Vale revisar a lista de tempos em tempos.
Alguns princípios atravessam tudo: