From 4a02292b3c5f9a435958f232adb05d97a8ff6861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=A3?= Date: Sun, 21 Sep 2025 18:01:10 -0300 Subject: [PATCH 1/3] =?UTF-8?q?feat(security):=20adiciona=20tratamento=20d?= =?UTF-8?q?e=20autentica=C3=A7=C3=A3o=20no=20filtro=20de=20seguran=C3=A7a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/SecurityFilter.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/SecurityFilter.java b/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/SecurityFilter.java index 8800880..f3fba20 100644 --- a/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/SecurityFilter.java +++ b/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/SecurityFilter.java @@ -1,16 +1,20 @@ package br.com.linktreeclone.security; import br.com.linktreeclone.repository.UserRepository; +import br.com.linktreeclone.exception.InvalidTokenException; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.servlet.HandlerExceptionResolver; import java.io.IOException; import java.util.UUID; @@ -24,24 +28,37 @@ public class SecurityFilter extends OncePerRequestFilter @Autowired private UserRepository userRepository; + @Autowired + @Qualifier("handlerExceptionResolver") + private HandlerExceptionResolver resolver; + @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = this.recoverToken(request); - if (token != null) { - String subject = tokenService.validateToken(token); - UUID userId = UUID.fromString(subject); + try + { + if (token != null) + { + String subject = tokenService.validateToken(token); + UUID userId = UUID.fromString(subject); + + UserDetails user = userRepository.findById(userId) + .orElseThrow(() -> new UsernameNotFoundException("Usuário não encontrado com o ID: " + userId)); - UserDetails user = userRepository.findById(userId) - .orElseThrow(() -> new RuntimeException("User Not Found")); + var authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + filterChain.doFilter(request, response); - var authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(authentication); } - filterChain.doFilter(request, response); + catch (Exception e) + { + resolver.resolveException(request, response, null, e); + } } private String recoverToken(HttpServletRequest request) @@ -55,4 +72,4 @@ private String recoverToken(HttpServletRequest request) return authHeader.replace("Bearer ", ""); } -} +} \ No newline at end of file From a36e6d85849d64197055c7a7d42a4437ec8fc469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=A3?= Date: Sun, 21 Sep 2025 18:01:24 -0300 Subject: [PATCH 2/3] =?UTF-8?q?feat(exception):=20adiciona=20tratamento=20?= =?UTF-8?q?detalhado=20para=20exce=C3=A7=C3=B5es=20de=20valida=C3=A7=C3=A3?= =?UTF-8?q?o=20de=20token=20JWT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../linktreeclone/security/TokenService.java | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/TokenService.java b/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/TokenService.java index 0a59aec..5119105 100644 --- a/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/TokenService.java +++ b/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/TokenService.java @@ -8,6 +8,12 @@ import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.UnsupportedJwtException; +import io.jsonwebtoken.security.SignatureException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.crypto.SecretKey; import java.nio.charset.StandardCharsets; @@ -24,6 +30,8 @@ public class TokenService private SecretKey key; + private static final Logger logger = LoggerFactory.getLogger(TokenService.class); + @PostConstruct public void init() { this.key = Keys.hmacShaKeyFor(jwtSecretString.getBytes(StandardCharsets.UTF_8)); @@ -53,8 +61,25 @@ public String validateToken(String token) .getBody() .getSubject(); } - catch (Exception e) { - throw new InvalidTokenException("Token JWT expirado ou inválido"); + catch (ExpiredJwtException ex) { + logger.error("Token JWT expirou: {}", ex.getMessage()); + throw new InvalidTokenException("Sua sessão expirou. Por favor, faça login novamente."); + } + catch (SignatureException ex) { + logger.error("Assinatura do JWT é inválida: {}", ex.getMessage()); + throw new InvalidTokenException("Assinatura do token é inválida."); + } + catch (MalformedJwtException ex) { + logger.error("Token JWT malformado: {}", ex.getMessage()); + throw new InvalidTokenException("Token malformado."); + } + catch (UnsupportedJwtException ex) { + logger.error("Token JWT não é suportado: {}", ex.getMessage()); + throw new InvalidTokenException("Este tipo de token não é suportado."); + } + catch (IllegalArgumentException ex) { + logger.error("O conteúdo do JWT está vazio: {}", ex.getMessage()); + throw new InvalidTokenException("Token inválido ou vazio."); } } } \ No newline at end of file From bbdd53968a0f9c21f462d74d4436121d443342d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=A3?= Date: Sun, 21 Sep 2025 18:02:22 -0300 Subject: [PATCH 3/3] =?UTF-8?q?refactor(exception):=20remove=20logs=20de?= =?UTF-8?q?=20erro=20para=20exce=C3=A7=C3=B5es=20de=20valida=C3=A7=C3=A3o?= =?UTF-8?q?=20de=20token=20JWT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/br/com/linktreeclone/security/TokenService.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/TokenService.java b/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/TokenService.java index 5119105..b135b25 100644 --- a/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/TokenService.java +++ b/linktreeclone-backend/src/main/java/br/com/linktreeclone/security/TokenService.java @@ -62,23 +62,18 @@ public String validateToken(String token) .getSubject(); } catch (ExpiredJwtException ex) { - logger.error("Token JWT expirou: {}", ex.getMessage()); throw new InvalidTokenException("Sua sessão expirou. Por favor, faça login novamente."); } catch (SignatureException ex) { - logger.error("Assinatura do JWT é inválida: {}", ex.getMessage()); throw new InvalidTokenException("Assinatura do token é inválida."); } catch (MalformedJwtException ex) { - logger.error("Token JWT malformado: {}", ex.getMessage()); throw new InvalidTokenException("Token malformado."); } catch (UnsupportedJwtException ex) { - logger.error("Token JWT não é suportado: {}", ex.getMessage()); throw new InvalidTokenException("Este tipo de token não é suportado."); } catch (IllegalArgumentException ex) { - logger.error("O conteúdo do JWT está vazio: {}", ex.getMessage()); throw new InvalidTokenException("Token inválido ou vazio."); } }