我的全局异常处理没有从 JwtTokenProvider 捕获新异常

问题描述 投票:0回答:1

我有一个 spirngboot 应用程序,我使用 JWT 来保证安全性,所以我在服务中有这段代码

public void registrarUsuario(RegisterDTO registerDTO){
    if (authRepository.existsByEmail(registerDTO.getEmail())){
        throw new UserAlreadyRegisterException();
    }
    Usuarios usuario = new Usuarios();
    usuario.setPrimer_nombre(registerDTO.getPrimer_nombre());
    usuario.setSegundo_nombre(registerDTO.getSegundo_nombre());
    usuario.setPrimer_apellido(registerDTO.getPrimer_apellido());
    usuario.setSegundo_apellido(registerDTO.getSegundo_apellido());
    usuario.setEmail(registerDTO.getEmail());
    usuario.setTelefono(registerDTO.getTelefono());
    Credenciales credencial = new Credenciales();
    credencial.setContraseña(passwordEncoder.encode(registerDTO.getContraseña()));
    credencialesRepository.save(credencial);
    usuario.setCredenciales(credencial);
    Roles roles = rolRepository.findByNombre("usuario").orElseThrow(() -> new NoSuchElementException("No se encontro el rol usuarios"));
    usuario.setRoles(Collections.singletonList(roles));
    authRepository.save(usuario);
}

当我尝试注册新用户时,如果该用户已经存在,我将创建异常 UserAlready... 并在响应中显示正确的格式

{
    "timeStamp": "2024-09-27T04:07:37.495+00:00",
    "code": "p-500",
    "message": "El usuario ya se encuentra registrado en la aplicacion",
    "url": "/api/v1/auth/register"
}

但是,当我尝试在另一个端点中的令牌过期时创建异常时,我的全局处理不会捕获此异常,它仅显示在我的控制台中。

这是我的代码

我的异常处理程序:

package com.api.reservavuelos.Exceptions;

import com.api.reservavuelos.DTO.ResponseExceptionDTO;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.Date;

@RestControllerAdvice
public class GlobalExceptionHandler {
    private Date tiempoactual = new Date();

    @ExceptionHandler(JwtTokenExpiredException.class)
    public ResponseEntity<ResponseExceptionDTO> handleJwtTokenExpiredException(HttpServletRequest request, JwtTokenExpiredException exception){
    return new ResponseEntity<>(new ResponseExceptionDTO(tiempoactual,"P-401", exception.getMessage(), request.getRequestURI()), HttpStatus.UNAUTHORIZED);
    }

    @ExceptionHandler(AuthenticationCredentialsNotFoundException.class)
    public ResponseEntity<ResponseExceptionDTO> handleAuthenticationCredentialsNotFoundException(HttpServletRequest request , AuthenticationCredentialsNotFoundException exception){
        return new ResponseEntity<>(new ResponseExceptionDTO(tiempoactual,"P-401", exception.getMessage(), request.getRequestURI()), HttpStatus.UNAUTHORIZED);
    }

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<ResponseExceptionDTO> handleUserNotFoundException(HttpServletRequest request, UserNotFoundException exception) {
        return new ResponseEntity<>(new ResponseExceptionDTO(tiempoactual,"P-404", exception.getMessage(), request.getRequestURI()), HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(UserAlreadyRegisterException.class)
    public ResponseEntity<ResponseExceptionDTO> handleUserAlreadyRegisterException(HttpServletRequest request, UserAlreadyRegisterException exception) {
        return new ResponseEntity<>(new ResponseExceptionDTO(tiempoactual,"p-500", exception.getMessage(), request.getRequestURI()), HttpStatus.BAD_REQUEST);
    }

}

我的 JwtTokenProvider

package com.api.reservavuelos.Security;

import com.api.reservavuelos.Exceptions.JwtTokenExpiredException;
import com.api.reservavuelos.Exceptions.UserAlreadyRegisterException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class JwtTokenProvider {

    public String generateToken(Authentication authentication) {
        // Implementación JWT Token generación
        String username = authentication.getName();
        Date tiempoactual = new Date();
        Date expiracion = new Date(tiempoactual.getTime() + ConstantSecurity.JWT_EXPIRATION_TOKEN);

        String Token = Jwts.builder()
                .setSubject(username)
                .setIssuedAt(tiempoactual)
                .setExpiration(expiracion)
                .signWith(SignatureAlgorithm.HS512, ConstantSecurity.JWT_FIRMA)
                .compact();

        return Token;
    }

    public String getUsernameFromToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(ConstantSecurity.JWT_FIRMA)
                .build()
                .parseClaimsJws(token)
                .getBody();

      return claims.getSubject();
    }

    public Boolean IsValidToken(String token) {
        try {
           Jwts.parser()
           .setSigningKey(ConstantSecurity.JWT_FIRMA)
           .build()
           .parseClaimsJws(token);
           return true;
        }catch (ExpiredJwtException e) {
         throw new JwtTokenExpiredException("Jwt ha expirado");
        } catch (AuthenticationCredentialsNotFoundException e)  {
            throw new AuthenticationCredentialsNotFoundException("Jwt esta incorrecto");
        }
    }
}
java spring spring-boot spring-mvc
1个回答
0
投票

我不确定您的安全过滤器是如何配置的,但我的经验是,在 MVC 接管并且

ControllerAdvice
出现之前调用调用 JWT 处理的安全过滤器。

我的解决方案(但我有一个自定义安全过滤器)是在过滤器中捕获 JWT 异常,并将带有错误消息的 401 直接写入响应中。比如:

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {
  try {
    // Process JWT and pass execute on if JWT is valid
  } catch (JwtException e) {
    response.setStatus(HttpStatus.UNAUTHORIZED.value());
    objectMapper.writeValue(response.getOutputStream(),
                                ErrorInfo.createWithMessage(e.getMessage(), request.getRequestURI()));
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.