Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ public class RestExceptionHandler
{
public record ErrorResponse(LocalDateTime timestamp, int status, String error, String message, String path) {}

@ExceptionHandler(InvalidTokenException.class)
public ResponseEntity<ErrorResponse> handleInvalidTokenException(InvalidTokenException ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
LocalDateTime.now(),
HttpStatus.FORBIDDEN.value(),
"Forbidden",
ex.getMessage(),
request.getDescription(false).replace("uri=", "")
);
return new ResponseEntity<>(errorResponse, HttpStatus.FORBIDDEN);
}

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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));
Expand Down Expand Up @@ -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.");
}
}
}
Loading