223 - API Hmac Com JWT
223 - API Hmac Com JWT
• AuthController,
• HMACController
• SecurityConfig.
Estrutura do Projeto
Dependências Necessárias
xml
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
1. Classe AuthController
1.1. Anotações
1.2. Campos
@PostMapping("/login")
public String login(@RequestBody UserCredentials credentials) {
if ("usuario".equals(credentials.getUsername()) &&
"senha".equals(credentials.getPassword())) {
return generateToken(credentials.getUsername());
} else {
throw new RuntimeException("Credenciais inválidas");
}
}
Detalhes do Método
java
private String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
Detalhes do Método
java
static class UserCredentials {
private String username;
private String password;
2.1. Anotações
2.2. Campos
Este método é um endpoint que aceita requisições POST e gera um token JWT
após validar as credenciais:
@PostMapping("/token/login")
public String authenticateUser(@RequestBody LoginRequest loginRequest) {
if (isValidUser(loginRequest.getUsername(), loginRequest.getPassword())) {
String token = generateToken(loginRequest.getUsername());
logger.info("User '{}' authenticated. Token generated: {}", loginRequest.getUsername(),
token);
return "Login successful! Token: " + token;
} else {
return "Invalid username or password!";
}
}
Detalhes do Método
Este método valida as credenciais do usuário com base nos valores mockados:
java
private String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 120000)) // Token válido por 120
segundos
.signWith(SignatureAlgorithm.HS256, SECRET_KEY.getBytes())
.compact();
}
Detalhes do Método
• Tempo de Expiração: Para facilitar testes, o token gerado é válido por 120
segundos.
• Assinatura: Utiliza a mesma lógica de assinatura que na classe anterior.
@PostMapping("/secure-data")
public String validateHMAC(@RequestBody SecureRequest requestData,
@RequestHeader("HMAC") String clientHMAC) {
try {
String serverHMAC = calculateHMAC(requestData.getMessage(), SECRET_KEY);
if (isRequestExpired(requestData.getTimestamp())) {
return "Request expired.";
}
if (serverHMAC.equals(clientHMAC)) {
return "HMAC validation successful!";
} else {
return "Invalid HMAC!";
}
} catch (Exception e) {
return "Error during HMAC validation!";
}
}
Detalhes do Método
• Parâmetros:
o @RequestBody SecureRequest requestData : Contém os dados a serem
validados e o timestamp da requisição.
o @RequestHeader("HMAC") String clientHMAC: O HMAC enviado pelo cliente
para validação.
• Cálculo do HMAC: O HMAC é calculado utilizando o método calculateHMAC.
• Validação do Timestamp: O método isRequestExpired verifica se a requisição
está expirada.
• Comparação do HMAC: Se o HMAC calculado no servidor corresponder ao
HMAC do cliente, a validação é bem-sucedida.
java
private String calculateHMAC(String data, String key) throws Exception {
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKey);
byte[] hmacData = mac.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(hmacData);
}
Detalhes do Método
• Criação da Chave Secreta: Utiliza SecretKeySpec para criar uma chave secreta
baseada na string key.
• Instância do Mac: Inicializa um objeto Mac com o algoritmo HmacSHA256.
• Cálculo do HMAC: O HMAC é calculado a partir da string de entrada e
convertido em Base64 para facilitar o transporte.
2.8. Classe Interna SecureRequest
java
class SecureRequest {
private String message;
private long timestamp;
Detalhes da Classe
3. Classe SecurityConfig
3.1. Anotações
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers("/api/token/login").permitAll()
.anyRequest().authenticated()
.and().httpBasic();
return http.build();
}
Detalhes do Método
4. Considerações
A implementação apresentada fornece uma base sólida para uma API segura
utilizando HMAC e JWT em Spring.