Por que Rust é a escolha ideal para autenticação?
\n\nSe você está escrevendo uma aplicação web em Rust, já está um passo à frente em segurança. Rust não perdoa erros de memória, o que significa que muitas vulnerabilidades (estouro de buffer, use-after-free) são eliminadas em tempo de compilação. Mas o compilador não vai protegê-lo de uma lógica de autenticação ruim. É sobre isso — como construir autenticação segura em Rust usando práticas modernas.
\n\nNeste artigo, montaremos um módulo de autenticação completo: hash de senhas com bcrypt, emissão de tokens JWT, verificação via middleware no Actix-web e proteção contra ataques comuns. O código será funcional — pode usá-lo no seu projeto.
1. Hash de senhas: por que bcrypt e não SHA-256?
\n\nMuitos iniciantes pensam: "Vou usar SHA-256, é rápido e confiável". E isso é um erro fatal. SHA é uma função de hash criptográfico, mas é rápida demais. Um atacante pode testar bilhões de combinações por segundo. Precisamos de uma função lenta, projetada especificamente para senhas.
\n\nbcrypt é o padrão ouro. Ele inclui "sal" (salt) e "fator de custo" (cost factor), que pode ser aumentado conforme o poder computacional cresce.
\n\nAdicionando bcrypt ao Cargo.toml
\n[dependencies]\nbcrypt = "0.15"\n\nGerando hash da senha
\nuse bcrypt::{hash, verify, DEFAULT_COST};\n\nfn hash_password(plain: &str) -> Result<String, bcrypt::BcryptError> {\n hash(plain, DEFAULT_COST) // cost = 12 (padrão)\n}\n\nfn verify_password(plain: &str, hashed: &str) -> bool {\n verify(plain, hashed).unwrap_or(false)\n}\n\nObserve: verify extrai o sal do próprio hash. Você não precisa armazenar o sal separadamente — ele já está dentro da string do hash. Isso é seguro e prático.
2. Tokens JWT: como não falhar na autenticação
\n\nApós o usuário digitar a senha, devemos emitir um "passe". JWT (JSON Web Token) é um formato compacto e autossuficiente. Mas o diabo está nos detalhes:
\n\n- \n
- Não armazene a chave secreta no código. Use variáveis de ambiente. \n
- Defina um tempo de vida curto. Token de acesso — 15–30 minutos, token de atualização — 7–30 dias. \n
- Não insira dados sensíveis no payload. Apenas o ID do usuário e a função. \n
Implementação de JWT com jsonwebtoken
\n\nuse jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};\nuse serde::{Serialize, Deserialize};\nuse chrono::{Utc, Duration};\n\n#[derive(Debug, Serialize, Deserialize)]\npub struct Claims {\n pub sub: String, // ID do usuário\n pub exp: usize, // timestamp de expiração\n pub iat: usize, // emitido em\n}\n\npub fn create_token(user_id: &str, secret: &str) -> Result<String, jsonwebtoken::errors::Error> {\n let now = Utc::now();\n let claims = Claims {\n sub: user_id.to_owned(),\n exp: (now + Duration::minutes(30)).timestamp() as usize,\n iat: now.timestamp() as usize,\n };\n encode(&Header::default(), &claims, &EncodingKey::from_secret(secret.as_bytes()))\n}\n\npub fn validate_token(token: &str, secret: &str) -> Result<Claims, jsonwebtoken::errors::Error> {\n let token_data = decode::<Claims>(\n token,\n &DecodingKey::from_secret(secret.as_bytes()),\n &Validation::default(),\n )?;\n Ok(token_data.claims)\n}\n\n3. Juntando tudo: Actix-web + middleware
\n\nAgora vamos combinar hash e JWT em uma aplicação web completa com Actix-web. Vamos escrever um middleware que verifica o token em cada requisição protegida.
\n\nEstrutura do projeto
\nsrc/\n├── main.rs\n├── auth.rs # hash, JWT\n├── middleware.rs # verificação de token\n└── handlers.rs #