Formulário de Login — Boas Práticas
Controlled inputs, validação client-side, UX de erros, proteção contra brute-force e CSRF.
Definição
Um formulário de login seguro combina: estado controlado via React, validação síncrona antes de chamar a API, tratamento explícito de erros da API (credenciais inválidas vs servidor fora), e proteção via CSRF token ou SameSite cookies. UX: desabilitar botão durante loading, focar no campo de erro, não revelar se email existe.
Problema → Solução
Problema
Formulários que enviam requisição com campos vazios, expõem se o email existe, não desabilitam o botão durante o request, ou mostram erros técnicos para o usuário.Solução
Validar client-side antes do fetch, usar estado loading/error explícito, mensagem genérica de erro ("Email ou senha inválidos"), cookie HttpOnly para o token de sessão, e rate limiting no servidor.Dica de entrevista
Tip
Nunca diga "email não encontrado" — sempre "email ou senha inválidos". Isso evita enumeração de usuários. O erro deve ser o mesmo para email errado e senha errada.Código
function LoginForm() {
const [form, setForm] = useState({ email: '', password: '' })
const [error, setError] = useState('')
const [loading, setLoading] = useState(false)
const handleSubmit = async (e) => {
e.preventDefault()
if (!form.email || !form.password) {
setError('Preencha todos os campos')
return
}
setLoading(true)
setError('')
try {
await login(form)
} catch {
setError('Email ou senha inválidos') // genérico
} finally {
setLoading(false)
}
}
return (
<form onSubmit={handleSubmit}>
<input type="email" value={form.email}
onChange={e => setForm(f => ({...f, email: e.target.value}))} />
<input type="password" value={form.password}
onChange={e => setForm(f => ({...f, password: e.target.value}))} />
{error && <p role="alert">{error}</p>}
<button type="submit" disabled={loading}>
{loading ? 'Entrando...' : 'Entrar'}
</button>
</form>
)
}Perguntas de entrevista
Q.Como evitar que o botão de submit seja clicado duas vezes?▾
A.Setar um estado `loading: true` no início do submit e `disabled={loading}` no botão. Isso previne double-submit que cria requests duplicados.
Q.Onde guardar o token JWT após login?▾
A.HttpOnly cookie (não acessível via JS, protege contra XSS). localStorage é conveniente mas vulnerável a XSS. sessionStorage some ao fechar a tab. Cookie HttpOnly + SameSite=Strict é o padrão de segurança.
Q.Como implementar "lembrar de mim"?▾
A.Ajustar o Max-Age do cookie de sessão. Com JWT, emitir um token com expiração longa (7-30 dias) vs curta (1h). O "lembrar" não deve armazenar a senha em lugar nenhum.
Termos relacionados
49/122← →