Como criar login com JWT em Java?
A autenticação com JSON Web Token (JWT) é uma forma segura e sem estado de proteger APIs REST. No Spring Boot, é possível gerar e validar JWTs facilmente utilizando bibliotecas como jjwt.
1. Adicionando Dependências
No pom.xml, adicione a biblioteca para manipulação de JWT:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.11.5</version>
</dependency>
2. Criando uma Classe para Gerenciar Tokens JWT
Crie uma classe JwtUtil
para gerar e validar tokens:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "minhaChaveSecreta";
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // 1 hora
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public static String extractUsername(String token) {
return getClaims(token).getSubject();
}
public static boolean isTokenValid(String token) {
return getClaims(token).getExpiration().after(new Date());
}
private static Claims getClaims(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
}
Explicação:
generateToken()
cria um token válido por 1 hora.extractUsername()
recupera o nome do usuário do token.isTokenValid()
verifica se o token é válido.
3. Criando um Endpoint de Login
Crie um Controller para autenticação:
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/auth")
public class AuthController {
@PostMapping("/login")
public Map<String, String> login(@RequestBody LoginRequest request) {
// Simulação de validação de usuário (substitua por consulta ao banco de dados)
if ("admin".equals(request.getUsername()) && "123456".equals(request.getPassword())) {
String token = JwtUtil.generateToken(request.getUsername());
Map<String, String> response = new HashMap<>();
response.put("token", token);
return response;
}
throw new RuntimeException("Credenciais inválidas");
}
}
class LoginRequest {
private String username;
private String password;
public String getUsername() { return username; }
public String getPassword() { return password; }
}
Explicação:
- Recebe um username e password.
- Valida o usuário (de forma simplificada, sem banco de dados).
- Retorna um token JWT caso a autenticação seja bem-sucedida.
4. Protegendo Endpoints com JWT
Agora, crie um filtro de autenticação para validar o token antes de processar as requisições:
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;
public class JwtFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
if (!JwtUtil.isTokenValid(token)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token inválido ou expirado");
return;
}
} else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token ausente");
return;
}
chain.doFilter(request, response);
}
}
Explicação:
- O filtro intercepta todas as requisições.
- Verifica se há um token JWT no cabeçalho
Authorization
.- Se o token for inválido ou ausente, bloqueia a requisição.
5. Aplicando o Filtro no Spring Security
No SecurityConfig
, adicione o filtro JWT:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/login").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
Explicação:
- O Spring Security exige autenticação para todos os endpoints, exceto
/auth/login
.- O JwtFilter é adicionado antes da autenticação padrão.
6. Testando a Autenticação com JWT
- Gerar o Token:
- Faça uma requisição POST para
http://localhost:8080/auth/login
. - Envie um JSON com:
- Faça uma requisição POST para
{
"username": "admin",
"password": "123456"
}
- Usar o Token nas Requisições:
- Copie o token JWT recebido.
- Faça uma requisição GET para qualquer endpoint protegido.
- No Postman, adicione um cabeçalho
Authorization
comBearer SEU_TOKEN_AQUI
.
Se o token for válido, a requisição será processada com sucesso.
Conclusão
O JWT permite que aplicações Java implementem autenticação sem estado, eliminando a necessidade de sessões no servidor. No Spring Boot, a configuração é simplificada com Spring Security, garantindo proteção para APIs REST.
Por que JWT é a melhor escolha para autenticação em APIs REST?
O JWT revolucionou a autenticação de APIs REST. Antes, os sistemas dependiam de sessões no servidor, o que gerava alto consumo de memória. Com o JWT, os clientes armazenam o token e o enviam a cada requisição, tornando a autenticação escalável e eficiente. Essa abordagem é amplamente utilizada em aplicações modernas e microsserviços.
Algumas aplicações:
- Autenticação segura para APIs REST
- Login sem necessidade de sessões no servidor
- Controle de acesso baseado em permissões
- Integração com Single Sign-On (SSO)
Dicas para quem está começando
- Use tokens curtos para aumentar a segurança
- Não armazene tokens no localStorage em aplicações web
- Proteja a chave secreta do JWT
- Utilize refresh tokens para manter a sessão ativa
Contribuições de Rodrigo Farias