Introdução: por que sua senha não é apenas uma string
\n\nImagine: você escreveu uma aplicação Java incrível para uma biblioteca online. Os usuários se registram, salvam favoritos, escrevem resenhas. E de repente — um vazamento de banco de dados. Todas as senhas em texto puro. Catástrofe? Com certeza! Em 2024, vazamentos de dados ocorrem a cada 39 segundos, e 81% deles estão relacionados à autenticação fraca. Se você programa em Java e quer que seu projeto não apareça nos noticiários de cibersegurança — este artigo é para você.
\n\nVamos abordar a autenticação segura em aplicações Java do início ao fim: desde hash de senhas até JWT e proteção contra CSRF. Sem teoria entediante, apenas código funcional e práticas reais. Vamos lá!
\n\n1. Hash de senhas: primeira linha de defesa
\n\nA primeira regra de segurança: nunca armazene senhas em texto puro. Mesmo que seu banco de dados seja o cálice sagrado, a criptografia de senhas é o mínimo obrigatório. Em Java, usam-se algoritmos como bcrypt, scrypt ou Argon2. Por que não MD5 ou SHA? Porque são muito rápidos — um invasor descobriria a senha em segundos.
\n\nPrática: bcrypt em ação
\nAdicione a dependência no pom.xml (Maven):
<dependency>\n <groupId>org.springframework.security</groupId>\n <artifactId>spring-security-crypto</artifactId>\n <version>6.2.0</version>\n</dependency>\n\n\nAgora, faça o hash da senha no registro:
\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\n\npublic class PasswordService {\n private final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();\n\n public String hashPassword(String rawPassword) {\n return encoder.encode(rawPassword); // gera salt automaticamente\n }\n\n public boolean checkPassword(String rawPassword, String storedHash) {\n return encoder.matches(rawPassword, storedHash);\n }\n}\n\n\nImportante: o bcrypt adiciona um salt aleatório automaticamente, então mesmo senhas iguais terão aparências diferentes. O custo (cost factor) padrão é 10, mas para sistemas críticos pode ser aumentado para 12-14.
\n\n2. JWT (JSON Web Tokens): sessão leve e segura
\n\nApós o registro, o usuário precisa confirmar sua identidade de alguma forma. Cookies? Pode ser, mas JWT é o padrão moderno para APIs REST. O token contém informações do usuário e é assinado com uma chave secreta. Sem sessões no servidor — tudo está no token.
\n\nCriação de JWT em Java
\nAdicione a biblioteca io.jsonwebtoken:jjwt:
<dependency>\n <groupId>io.jsonwebtoken</groupId>\n <artifactId>jjwt-api</artifactId>\n <version>0.12.3</version>\n</dependency>\n\n\nGeração do token:
\nimport io.jsonwebtoken.Jwts;\nimport io.jsonwebtoken.security.Keys;\nimport javax.crypto.SecretKey;\nimport java.util.Date;\n\npublic class JwtUtil {\n private final SecretKey key = Keys.hmacShaKeyFor("chave_secreta_com_pelo_menos_256_bits".getBytes());\n\n public String generateToken(String username) {\n return Jwts.builder()\n .subject(username)\n .issuedAt(new Date())\n .expiration(new Date(System.currentTimeMillis() + 3600000)) // 1 hora\n .signWith(key)\n .compact();\n }\n\n public String extractUsername(String token) {\n return Jwts.parser()\n .verifyWith(key)\n .build()\n .parseSignedClaims(token)\n .getPayload()\n .getSubject();\n }\n}\n\n\nDica: não armazene a chave secreta no código! Use variáveis de ambiente ou Vault. E nunca coloque dados confidenciais (senhas, números de cartão) no JWT — o token pode ser decodificado sem a assinatura.
\n\n