07 - Cookies, Sessões e Cache
video: https://youtu.be/... no frontmatter da nota.Cookies, Sessões e Cache
1. Definição e Contexto
HTTP é stateless: cada requisição é independente, sem memória de requisições anteriores. Para manter estado entre requisições (autenticação, preferências, carrinho de compras), três mecanismos foram criados: Cookies (client-side), Sessões (server-side) e Cache (aceleração). Eles coexistem em qualquer aplicação web moderna e são alvo frequente de bugs e ataques.
Distinção
| Mecanismo | Onde mora | Função principal |
|---|---|---|
| Cookie | Cliente (browser) | Identificação, preferências |
| Sessão | Servidor (RAM/DB) | Estado autenticado, dados sensíveis |
| Cache | Cliente/CDN/Proxy | Aceleração, redução de latência |
2. Cookies — Estrutura
Um cookie é um par nome-valor enviado pelo servidor via header Set-Cookie e devolvido pelo cliente via header Cookie.
Exemplo de Set-Cookie
HTTP/1.1 200 OK
Set-Cookie: session_id=abc123; Domain=exemplo.com; Path=/; Max-Age=3600; HttpOnly; Secure; SameSite=Lax
Set-Cookie: theme=dark; Domain=exemplo.com; Path=/; Max-Age=31536000; SameSite=Strict
Set-Cookie: tracking_id=xyz789; Domain=.exemplo.com; Path=/; Expires=Wed, 21 Oct 2025 07:28:00 GMT
Exemplo de Cookie (Requisição Posterior)
GET /dashboard HTTP/1.1
Host: exemplo.com
Cookie: session_id=abc123; theme=dark; tracking_id=xyz789
3. Atributos de Cookie
| Atributo | Função |
|---|---|
Domain=exemplo.com |
Domínios (e subdomínios) que recebem o cookie |
Path=/admin |
Limita a um prefixo de URL |
Expires=<date> |
Data absoluta de expiração |
Max-Age=3600 |
Segundos a partir de agora (preferível) |
Secure |
Envia só sobre HTTPS |
HttpOnly |
Inacessível via JavaScript (proteção XSS) |
SameSite=Strict\|Lax\|None |
Controla envio em cross-site |
Sem Expires ou Max-Age, o cookie é de sessão (descartado ao fechar o browser). Com eles, é persistente. Lax é o default desde Chrome 80+ (2020). None exige Secure explícito.
SameSite
| Valor | Comportamento |
|---|---|
Strict |
Apenas requisições same-site |
Lax |
Same-site + top-level navigation GET cross-site |
None |
Cross-site sempre (exige Secure) |
Cookies de sessão devem usar Lax ou Strict. Cookies de tracking/analytics usam None; Secure. Strict/Lax bloqueiam CSRF simples.
Prefixos __Host- e __Secure-
__Host-: deve ser host-only (semDomain),Path=/eSecure. Garante que o cookie só vale para o host exato, evitando vazamento para subdomínios.__Secure-: deve terSecure(sem outras exigências).
Set-Cookie: __Host-session=abc123; Path=/; Secure; HttpOnly; SameSite=Strict
4. Tipos de Cookie
| Tipo | Propósito | Duração | Exemplo |
|---|---|---|---|
| Essencial | Login, sessão | Sessão / curta | session_id |
| Preferência | Tema, idioma | Longa (1 ano) | theme=dark |
| Analytics | Métricas de uso | Curta-média | _ga, _gid |
| Marketing | Retargeting, ads | Média | _fbp, fr |
| Third-party | Cross-site tracking | Variável | IDE (Doubleclick) |
Cookies third-party (terceira parte) são enviados em requisições para domínios diferentes da página atual (imagens, iframes). Browsers bloqueiam-nos por padrão desde 2024 (Chrome, Safari, Firefox).
5. Sessões — Estado Server-Side
Cliente recebe cookie com identificador opaco (session_id=abc123). Servidor guarda o estado real (user_id, permissões, carrinho) em RAM, Redis ou DB. A cada requisição, servidor consulta o session_id e recupera o estado.
Vantagens: dados sensíveis não ficam no cliente (LGPD); tamanho ilimitado; pode ser invalidado imediatamente.
Desvantagens: custo de storage/lookup por requisição; sessões em RAM são perdidas em restart; em clusters, requer storage compartilhado (Redis, sticky sessions ou JWT stateless).
JWT vs Sessão
| Aspecto | Sessão (server-side) | JWT (stateless) |
|---|---|---|
| Estado | Servidor | Cliente |
| Storage | Redis/DB | Cookie/localStorage |
| Tamanho do token | Curto (UUID) | Longo (base64 JSON + assinatura) |
| Revogação | Imediata | Difícil (exige blacklist) |
| Escala horizontal | Sticky sessions ou Redis | Trivial |
6. Cache HTTP
Headers de Cache
| Header | Função |
|---|---|
Cache-Control |
Diretivas de cache (max-age, no-store, public, private) |
ETag / If-None-Match |
Identificador de versão / validação |
Last-Modified / If-Modified-Since |
Data de modificação / validação |
Vary |
Varia cache por header do cliente |
Expires |
Data de expiração (legacy, preferir max-age) |
Age |
Idade do objeto no cache |
Cache-Control — Diretivas
Cache-Control: public, max-age=3600, s-maxage=86400, stale-while-revalidate=60
| Diretiva | Significado |
|---|---|
public |
Qualquer cache pode armazenar |
private |
Apenas cache do browser (não CDN) |
no-cache |
Valida com servidor antes de usar |
no-store |
Não armazenar de forma alguma |
max-age=N |
Tempo máximo de frescor (segundos) |
s-maxage=N |
Tempo máximo para caches compartilhados (CDN) |
must-revalidate |
Revalidar obrigatoriamente após expirar |
immutable |
Recurso nunca muda; cliente nunca revalida |
stale-while-revalidate=N |
Permite servir stale enquanto revalida em background |
ETag e Last-Modified
- ETag: hash (SHA, MD5 ou timestamp) que identifica a versão do recurso. Cliente envia
If-None-Match: "abc123"; servidor responde304 Not Modifiedse ainda for a mesma versão. - Last-Modified: data de última modificação. Cliente envia
If-Modified-Since. Menos preciso que ETag (resolução de 1s).
Fluxo típico de validação: primeira requisição recebe ETag: "v1" e Cache-Control: max-age=3600. Após expirar, cliente envia If-None-Match: "v1"; se o recurso não mudou, servidor responde 304 sem corpo (economia de banda).
Vary
Indica que o cache varia conforme um header do cliente. Para conteúdo comprimido: Content-Encoding: gzip + Vary: Accept-Encoding — cache mantém duas versões (br e gzip).
7. Estratégias de Cache em CDN
- Cache-First (SWR):
Cache-Control: public, max-age=60, stale-while-revalidate=86400— CDN serve versão cacheada por 60s; após isso serve stale e revalida em background. Bom para conteúdo semi-dinâmico (home pages, listagens). - Long Cache com Hashing:
Cache-Control: public, max-age=31536000, immutable— assets com hash no nome (app.abc123.js) podem ser cacheados por 1 ano. Quando há mudança, gera-se novo hash (app.def456.js), forçando refetch. - No-Store:
Cache-Control: no-store— APIs autenticadas não devem ser cacheadas. - Surrogate-Control: Header CDN-specific (
Surrogate-Control: max-age=86400; Cache-Control: no-cache) — CDN cacheia por 1 dia, browser não cacheia. Permite purge via API quando o conteúdo muda.
8. Invalidação de Cache
- Purge via API: CDNs (Cloudflare, CloudFront, Akamai) expõem API para purge de URLs específicas ou por tag.
- Cache Busting: Renomear arquivo com novo hash (
/styles.v1.css→/styles.v2.css), evitando invalidar. - Soft Purge: Marca conteúdo como stale, mas não apaga. Continua servindo durante revalidação. Reduz origem load.
9. Boas Práticas
Cookies
- Sessão:
HttpOnly,Secure,SameSite=LaxouStrict, prefix__Host-. - Preferência:
SameSite=Lax,Max-Ageadequado. - Tracking:
SameSite=None; Secure, com consentimento LGPD/GDPR. - Limite ~50 cookies por domínio, 4KB cada.
- Nunca armazenar senhas/PII em cookies sem criptografia.
Sessões
- ID opaco (UUID v4, 128 bits). Não usar identificador sequencial.
- Rotação de ID após login (prevenir session fixation).
- Expiração absoluta (24h) e por inatividade (30 min).
- Redis para clusters; RAM exige sticky sessions.
Cache
- Assets estáticos:
max-age=31536000, immutablecom hash no nome. - HTML:
no-cache(revalida sempre). - APIs autenticadas:
no-store. - Listagens públicas:
max-age=60, stale-while-revalidate=300. - Sempre definir
Vary: Accept-Encoding, Acceptquando relevante.
10. Erros Comuns
| Erro | Causa | Correção |
|---|---|---|
| Cookie capturado por XSS | Falta HttpOnly |
Habilitar HttpOnly para sessões |
| CSRF funciona | SameSite=None sem necessidade |
Usar Lax ou Strict |
| Sessão fixada após login | Sem rotação de ID | Regerar ID no login |
| Cache mostra conteúdo antigo | Sem cache-busting em deploy | Hash no filename |
| Cookies vazam para subdomínio | Domain=.exemplo.com largo |
Usar __Host- prefix |
| CDN cacheia resposta personalizada | Falta Vary ou private |
Cache-Control: private ou Vary: Cookie |
11. Resumo Técnico
| Mecanismo | Header | Default | Quando usar |
|---|---|---|---|
| Cookie | Set-Cookie/Cookie | Sem estado | Identificação |
| Sessão | Cookie + Server State | RAM | Estado autenticado |
| Cache-Control | max-age | No-cache | Controle fino |
| ETag | If-None-Match | - | Revalidação |
| Vary | - | - | Variação por header |
12. Conclusão
Cookies, sessões e cache formam o tripé que sustenta a web stateful moderna sobre um protocolo stateless. Cookies gerenciam identificação e preferências no cliente, com atributos como HttpOnly, Secure e SameSite essenciais para segurança. Sessões server-side guardam estado sensível com revogação imediata, frequentemente em Redis para escalabilidade. Cache HTTP, via Cache-Control, ETag e Vary, reduz drasticamente latência e custo de servidor quando bem configurado. Engenheiros devem dominar a interação entre esses três mecanismos, evitando erros clássicos como cookies sem HttpOnly, sessões sem rotação de ID, e assets sem cache-busting. A conformidade com LGPD/GDPR adiciona camada de governança sobre cookies de tracking, exigindo consentimento explícito do usuário.